ZW3D二次开发_入门_Action与Ribbon菜单定制--转自 知乎 捣蛋龙

ZW3D二次开发_入门_Action与Ribbon菜单定制

 
5 人赞同了该文章
目录
收起
ZW3D二开入门目录 - 知乎 (zhihu.com)
最新测试环境:2025 SP
前言
定制Ribbon菜单
1.新建工作区
2.定义"行为"
3.定义自定义Ribbon文件
4.编写策略文件
5.编写引导程序
6.多环境差异化策略
7.定制原生菜单
8.无法正确显示菜单的终极解决方案
附件
关于ZW3D二开问题咨询与合作

ZW3D二开入门目录 - 知乎 (zhihu.com)

最新测试环境:2025 SP

前言

这一章介绍如何定制自己的Ribbon菜单,以及如何定制ZW3D原生Ribbon菜单。修改菜单时建议先关闭ZW3D,修改后再启动ZW3D。

学习时间:120min+

学习本节前,请先学习基础概念

ZW3D二次开发_入门_菜单介绍 - 知乎 (zhihu.com)

定制Ribbon菜单

1.新建工作区

首先需要新建一些文件夹来放置各种菜单,我选择在桌面新建一个叫RibbonPageUI的文件夹,文件夹内的结构如下(vs code把RibbonPageUI显示成RIBBONPAGEUI了,实际上是RibbonPageUI):

除了RibbonPageUI这个文件夹名字可以改,其它的都要按照固定写法,不然ZW3D会读取不到菜单。

2.定义"行为"

在ResourcePool下新建一个Action.zcui文件,这个文件用来定义行为,文件名是随意的,因为最终ZW3D是根据XML中的内容辨识一个.zcui文件定义了什么东西。不过还是建议使用XX_Action_XX这种命名方式,因为后期文件多了以后,维护起来比较方便。

后续不管是做Ribbon菜单,还是做其它菜单,都要基于Action.zcui文件,做菜单的过程,其实就是把一组行为装进菜单容器的过程。下面先定义一个“ID_~CommandA”行为,在Action.zcui写入如下内容:

<?xml version="1.0" encoding="UTF-8"?>
<Actions system="false">
	<Action name="ID_~CommandA" type="button">
		<Form />
		<Text>
			<Ribbon>命令A</Ribbon>
			<Menu>命令A</Menu>
		</Text>
		<Icon>测试命令A</Icon>
		<Hint>这是测试命令A</Hint>
		<Help />
		<Desc />
		<Script>~CommandA</Script>
	</Action>
</Actions>

介绍一下这里面比较关键的字段

字段说明属性
Ribbon 行为插入Ribbon菜单时的显示的文本信息
Menu 行为插入普通菜单时的显示的文本信息,一般跟Ribbon设置成一样的值即可
Icon 定义图标,有些菜单或者样式本身不支持图标显示的话,就不会显示图标、仅显示文字,图标是用png格式的图片。

如果图标不在搜索路径下,则需要写完整路径,如:
<Icon>C:\Users\Administrator\Pictures\测试命令A.png</Icon>

如果图标在搜索路径下,则写图片名就行:
<Icon>测试命令A</Icon>
Script 定义执行脚本,即点击按钮后,向ZW3D发送什么命令
Action 定义行为的基本信息 #name#
行为的名字,相当于赋予行为一个“代号”,它的格式一定是ID_<Script>
#type#
行为的类型,目前只有button类型

基于上述信息,我们在“Resource\icons”中添加如下四个图片,后面我们会在引导程序中将icons文件夹的父文件夹添加到搜索路径,所以本例涉及的所有行为的Icon字段写图标名就行,不需要写全路径。

在写自定义Ribbon菜单之前,我们可以仿照“ID_~CommandA”,在Action.zcui里再定义“ID_~CommandB”、“ID_~CommandC”、“ID_~CommandD”三个行为。

3.定义自定义Ribbon文件

我们准备做下面这种菜单:

解析一下这个Ribbon的结构:

最外层是一个名为“测试命令1”Ribbon页,内部包含两个组,分别是“1组”和“2组”,每个组有且仅有一个组面板。

“1组”下有4个控件,4个控件的行为分别是“ID_~CommandA”、“ID_~CommandB”、“ID_~CommandC”、“ID_~CommandD”,其中A与B是大图标样式,C与D是小图标样式。

“2组”下有一个控件菜单,控件菜单中包含了4个控件,每个控件的行为分别是“ID_~CommandA”、“ID_~CommandB”、“ID_~CommandC”、“ID_~CommandD”,默认控件是“ID_~CommandA”。

基于上述信息,在ResourcePool文件夹中新建RibbonPage.zcui文件,然后在“Resource\Settings\Default\ResourcePool\RibbonPage.zcui”里写如下内容:

<?xml version="1.0" encoding="UTF-8"?>
<RibbonPages>
	<RibbonPage name="RIBBON_PAGE1" text="测试命令1" visible="true">
		<RibbonGroup name="RIBBON_PAGE1_GROUP1" text = "1组" visible="true">
			<GroupPanel name="RIBBON_PAGE1_GROUP1_PANEL1">
				<Control action="ID_~CommandA" visible="true" buttonStyle="4" />
				<Control action="ID_~CommandB" visible="true" buttonStyle="4" />
				<Control action="ID_~CommandC" visible="true" buttonStyle="2" />
				<Control action="ID_~CommandD" visible="true" buttonStyle="2" />
			</GroupPanel>
		</RibbonGroup>
		<RibbonGroup name="RIBBON_PAGE1_GROUP2" text = "2组" visible="true">
			<GroupPanel name="RIBBON_PAGE1_GROUP2_PANEL1">
				<ControlMenu name="RIBBON_PAGE1_GROUP2_PANEL1_MENU1" defaultAction="ID_~CommandA" visible="true" buttonStyle="4">
					<Item action="ID_~CommandA" visible="true" />
					<Item action="ID_~CommandB" visible="true" />
					<Item action="ID_~CommandC" visible="true" />
					<Item action="ID_~CommandD" visible="true" />
				</ControlMenu>
			</GroupPanel>
		</RibbonGroup>
	</RibbonPage>
</RibbonPages>

介绍一下相关的字段

字段说明属性
RibbonPages Ribbon菜单集合  
RibbonPage Ribbon菜单定义 #name#
(必需),Ribbon菜单的名字
#text#
(必需),显示文本
#visible#
(必需),显示状态,建议="true"
RibbonGroup 定义Ribbon菜单下的组 #name#
(必需),组的名字
#text#
(必需),显示文本
#visible#
(必需),显示状态,建议="true"
GroupPanel 定义组下的组面板,一个RibbonGroup里面有且仅有一个GroupPanel,至少目前测试下来是这样 #name#
(必需),组面板的名字
Control 定义控件,一个组面板里可以有多个控件 #action#
(必需),引用行为的名字#visible#
(必需),显示状态,建议="true"
#buttonStyle#
(必需),按钮样式,0=仅图标;1=仅文本;2=小图标;4=大图标
ControlMenu 定义控件菜单,可以下拉选择 #name#
(必需),控件菜单的名字
#defaultAction#
(必需),默认引用行为,一般用第一个下拉控件的行为
#visible#
(必需),默认显示状态,建议="true"
#buttonStyle#
(必需),按钮样式,0=仅图标;1=仅文本;2=小图标;4=大图标
Item 定义控件菜单中的下拉控件 #action#
(必需),引用行为的名字
#visible#
(必需),显示状态,建议="true"

4.编写策略文件

在Strategy文件夹下新建一个Environment-10-Part文件夹,表示我要修改零件环境下的菜单,然后在Environment-10-Part文件夹中新建一个LayoutStrategy-4-Expert.zcui文件夹,表示我要修改专家角色的菜单,然后在“Resource\Settings\Default\Strategy\Environment-10-Part\LayoutStrategy-4-Expert.zcui”中写入下面的内容:

<?xml version="1.0" encoding="UTF-8"?>
<Strategy profileType="UIProfile" environment="10" role="4-Expert">
	<DefaultCustomizations>
		<Insert type="RibbonPage" name="RIBBON_PAGE1" topCollection="Layout_10_Part" leftSibling="#InsertAtLast" />
	</DefaultCustomizations>
</Strategy>

<Strategy>字段定义了一个策略,其中environment属性表示要适配的环境,role表示要适配的角色,下面解释一下角色与环境的概念。

角色是指下图里的四个可选项,双击可以切换,区别就是初级只显示一部分基础功能,专家显示全部功能。

四个角色的role属性如下:

角色role
全角色通用 #AllRoles
初级 1-Primary
中级 2-Intermediate_default
高级 3-Advanced
专家 4-Expert

环境是指软件当前打开的哪个界面,比如初始界面,零件,装配,工程图,这些界面下的菜单是不一样的,所以引入了环境的概念,下面是环境对应的environment属性以及大概的解释:

环境(英文)环境(中文说明)environment
Top 软件初始界面 0
Root 多根文件初始界面(.Z3) 1
Z3 多根文件零件/装配激活界面(.Z3) 2
Sketch 草图(.Z3/.Z3SKH) 3
Sheet *工程图(.Z3/.Z3DRW) 4
Packet 工程图包(旧版本才有该环境) 5
Cam 加工(.Z3/.Z3CAM) 6
Animation 动画 7
ExplodedView 爆炸视图 8
3DSketch 三维草图 9
Part *单根零件(.Z3PRT/Standard) 10
ECAD Assembly ECAD装配(.Z3ASM/ECAD) 11
ECAD Part ECAD零件(.Z3PRT/ECAD) 12
Assembly *单根装配(.Z3ASM/Standard) 13
Master Layout 布局(.Z3PRT/Master Layout) 17

4,10,13是最常用的,对应制图,零件和装配。

<Insert type="RibbonPage"...>,表示要插入一个Ribbon菜单,topCollection="Layout_10_Part"属性表示菜单插入到零件环境。不同环境的topCollection名称可以打开原生菜单定义文件看看,默认在“C:\Program Files\ZWSOFT\ZW3D 2025\Settings\ResourcePool\Layouts”路径。

leftSibling="#InsertAtLast"表示该自定义的菜单要插入到Ribbon选项卡的最后面。

如果想指定某个Ribbon在我们自定义Ribbon的左边或者右边,可以设置leftSibling(rightSibing)=其它Ribbon的名字。比如想让原生的“造型”Ribbon选项卡在自定义Ribbon菜单的右边,可以用rightSibing="UiFtrTool"属性,类似的如果想让原生的“造型”Ribbon选项卡在自定义Ribbon菜单的左边,可以设置leftSibing="UiFtrTool"。

5.编写引导程序

菜单随便放在一个位置,ZW3D不会无缘无故自己加载它,需要我们写一个DLL作为引导程序,DLL的开发介绍可以参考这个文章:

ZW3D二次开发入门_二次开发程序创建(2025+VS2022) - 知乎 (zhihu.com)

我的工程叫Z3Project,所以引导程序如下:

int Z3ProjectInit() {
    cvxPathAdd("C:\\Users\\Administrator\\Desktop\\RibbonPageUI\\Resource");//添加搜索路径
    ZwProfileModuleNameRegister("RibbonPageUI");//注册自定义菜单模块
    return 0;
}

int Z3ProjectExit() {
    return 0;
}

cvxPathAdd是添加搜索路径,需要定位到自定义菜单路径的Resource文件夹,ZwProfileModuleNameRegister是注册自定义菜单模块,即Resource文件夹上一级文件夹的名称。

写完引导程序后,我们还需要预加载引导程序,即确保ZW3D启动时,引导程序一定会被加载,有两种常用方式可参考:

1.手动启动ZW3D,手动加载引导程序DLL,再关闭ZW3D,下次打开ZW3D时,引导程序DLL就会被自动加载

2.如果你的插件要给别人用,可以在安装包里写注册表来预加载DLL,注册表写法可参考下图信息(Resource是指定zrc资源文件用的,可以不写)

现在打开ZW3D,新建一个零件,就能看见菜单了:

6.多环境差异化策略

假设自定义Ribbon菜单需要部署在零件、装配、工程图下,那么我们需要写三个策略文件,内部基本一致,都是插入“RIBBON_PAGE1”,结构如下所示:

如果在不同环境下,需要对自定义Ribbon做局部调整,一个比较容易想到的方法是,根据需求再做几个RibbonPage,然后把这些不同的RibbonPage插入到具体环境中。这样明显是可行的,不过这样会产生很多重复工作量,维护起来也不方便,推荐使用写策略文件的方式来实现差异化,下面是关于RibbonPage常用的一些动作与对应字段属性。

动作字段属性
插入”Ribbon菜单“ Insert #type#="RibbonPage"
(必需)
#name#
(必需),Ribbon菜单的名字
#leftSibling/rightSibling#
(必需),定义自定义菜单左边(右边)的菜单,"#InsertAtLast"表示插入到最后
#topCollection#
(必需),插入哪个菜单集

**内嵌property字段的属性**

#text#
显示文本,对于已定义的元素,(可选),对于未定义的元素,(必需)
#visible#
显示状态,对于已定义的元素,(不填写),对于未定义的元素,(必需)填写
删除”Ribbon菜单“ Remove #type#="RibbonPage"
(必需)
#name#
(必需),Ribbon菜单的名字
#topCollection#
(必需),从哪个菜单集删除Ribbon菜单
插入“组”(不能插入已定义的组) Insert #type#="RibbonGroup"
(必需)
#name#=组的名字
(必需)
#topParent#
(必需),插入哪个RibbonPage
#parent#
(必需),插入哪个父节点
#leftSibling/rightSibling#
(必需),定义自定义菜单左边/右边的菜单,"#InsertAtLast"表示插入到最后

**内嵌property字段的属性**

#text#
(必需),显示文本
#visible#
(必需),显示状态
删除“组” Remove #type#="RibbonGroup"
(必需)
#name#=指定组的名字
(必需)
#topParent#
(必需),删除哪个RibbonPage下的组
#parent#
(必需),删除哪个父节点下的组
插入”组“下的“组面板”(插入组后一定要插入组面板,控件无法直接加到组里,只能加到组面版里,无法插入已定义的组面板) Insert #type#="GroupPanel"
(必需)
#name#=组面板的名
(必需)
#topParent#
插入哪个RibbonPage
(必需)
#parent#
插入哪个父节点
(必需)
插入“控件” Insert #type#="Control"
(必需)
#name#=行为的名字
(必需)
#topParent#
插入哪个<RibbonPage>
(必需)
#parent#
插入哪个<GroupPanel>
(必需)
#leftSibling/rightSibling#
(必需),定义自定义菜单左边/右边的菜单,"#InsertAtLast"表示插入到最后

**内嵌property字段的属性**

#buttonStyle#
(必需),按钮样式,0=仅图标;1=仅文本;2=小图标;4=大按钮
#visible#
(必需),显示状态
删除“控件” Remove #type#="Control"
(必需)
#name#=指定行为的名字
(必需)
#topParent#
(必需),删除哪个RibbonPage下的控件
#parent#
(必需),删除哪个父节点下的控件
插入“控件菜单”(不能插入已定义的控件菜单) Insert #type#="ControlMenu"
(必需)
#name#=控件菜单名
(必需)
#topParent#
插入哪个<RibbonPage>
(必需)
#parent#
插入哪个父节点下
(必需)
#leftSibling/rightSibling#
(必需),定义自定义菜单左边/右边的菜单,"#InsertAtLast"表示插入到最后

**内嵌property字段的属性**

#defaultAction#
(必需),默认行为的名字
#buttonStyle#
(必需),按钮样式,0=仅图标;1=仅文本;2=小图标;4=大按钮
#visible#
(必需),显示状态
删除“控件菜单” Remove #type#="ControlMenu"
(必需)
#name#=指定控件菜单的名字
(必需)
#topParent#
(必需),删除哪个RibbonPage下的控件菜单
#parent#
(必需),删除哪个父节点下的控件菜单
插入“控件菜单”下的控件 Insert #type#="Item"
(必需)
#name#=行为的名字
(必需)
#topParent#
(必需),插入哪个RibbonPage
#parent#
(必需),插入哪个父节点下
#leftSibling/rightSibling#
(必需),定义自定义菜单左边/右边的菜单,"#InsertAtLast"表示插入到最后

**内嵌property字段的属性**

#visible#
(必需),显示状态
删除“控件菜单”下的控件 Remove #type#="Item"
(必需)
#name#=指定行为的名字
(必需)
#topParent#
(必需),删除哪个RibbonPage下的控件
#parent#
(必需),删除哪个父节点下的控件
修改 Modify 支持以下属性的字段都可以修改
#visible#
#text#

根据上面的信息,如果我们想在装配环境下,删除“1组”的后两个控件,删除“2组”,新建“3组”(注意,新建组时也需要新建组面版),并向3组中添加2个独立控件和一个控件菜单,并向控件菜单里添加两个控件,则需要对Environment-13-Assembly的LayoutStrategy-4-Expert.zcui文件做如下改动:

<?xml version="1.0" encoding="UTF-8"?>
<Strategy profileType="UIProfile" environment="13" role="4-Expert">
	<DefaultCustomizations>
		<Insert type="RibbonPage" name="RIBBON_PAGE1" topCollection="Layout_13_Asm" leftSibling="#InsertAtLast" />
		<Remove type="Control" name="ID_~CommandC" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1_GROUP1_PANEL1" />
		<Remove type="Control" name="ID_~CommandD" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1_GROUP1_PANEL1" />
		<Remove type="RibbonGroup" name="RIBBON_PAGE1_GROUP2" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1" />
		<Insert type="RibbonGroup" name="RIBBON_PAGE1_GROUP3" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1" leftSibling="#InsertAtLast">
			<property text = "3组" visible="true" />
		</Insert>
		<Insert type="GroupPanel" name="RIBBON_PAGE1_GROUP3_PANEL1" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1_GROUP3" />
		<Insert type="Control" name="ID_~CommandA" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1_GROUP3_PANEL1" leftSibling="#InsertAtLast">
			<property buttonStyle="4" visible="true" />
		</Insert>
		<Insert type="Control" name="ID_~CommandB" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1_GROUP3_PANEL1" leftSibling="#InsertAtLast">
			<property buttonStyle="4" visible="true" />
		</Insert>
		<Insert type="ControlMenu" name="RIBBON_PAGE1_GROUP3_PANEL1_MENU1" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1_GROUP3_PANEL1" leftSibling="#InsertAtLast">
			<property buttonStyle="4" defaultAction="ID_~CommandA" visible = "true" />
		</Insert>
		<Insert type="Item" name="ID_~CommandA" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1_GROUP3_PANEL1_MENU1" leftSibling="#InsertAtLast">
			<property visible="true" />
		</Insert>
		<Insert type="Item" name="ID_~CommandB" topParent="RIBBON_PAGE1" parent="RIBBON_PAGE1_GROUP3_PANEL1_MENU1" leftSibling="#InsertAtLast">
			<property visible="true" />
		</Insert>
	</DefaultCustomizations>
</Strategy>

改动后,可以看到自定义Ribbon的前后对比情况

7.定制原生菜单

对原生菜单进行编辑,与上述差异化策略写法一致,唯一的不同点是,操作的对象都是原生菜单里的内容。

假设我想把零件环境专家角色的“造型”RibbonPage中的“编辑模型”组屏蔽掉,然后在“基础造型”组中插入“抽壳”命令,即下图所示:

想做到上图的效果,我们对Environment-10-Part的LayoutStrategy-4-Expert.zcui文件做如下改动:

<?xml version="1.0" encoding="UTF-8"?>
<Strategy profileType="UIProfile" environment="10" role="4-Expert">
	<DefaultCustomizations>
		<Insert type="RibbonPage" name="RIBBON_PAGE1" topCollection="Layout_10_Part" leftSibling="#InsertAtLast" />
		<Remove type="RibbonGroup" name="GROUP122719" topParent="UiFtrTool" parent="UiFtrTool" />
		<Insert type="Control" name="ID_!FtShell1" topParent="UiFtrTool" parent="BasicShapes_GroupPanel" leftSibling="#InsertAtLast">
			<property buttonStyle="4" visible="true"/>
		</Insert>
	</DefaultCustomizations>
</Strategy>

原生RibbonPage的名字可以打开具体环境下的Layout文件查看,以零件环境为例,默认在C:\Program Files\ZWSOFT\ZW3D 2025\Settings\ResourcePool\Layouts\Layout_10_Part.zcui的<RibbonPages>中。

这15个<RibbonPage>就对应了零件环境下的这些Ribbon,至于如何确认具体哪个RibbonPage对应哪个界面里的Ribbon选项卡,这个目前没啥好办法

如果想知道原生Ribbon的各种内部标识是什么,可以用VS Code搜索安装路径下的Settings文件夹,默认是”C:\Program Files\ZWSOFT\ZW3D 2025\Settings\ResourcePool\RibbonPages.zcui“,比如我首先从Layout_10_Part.zcui知道了零件环境的“造型“RibbonPage叫”UiFtrTool“,那我们可以去Settings下的RibbonPages.zcui找到它的定义:

这部分定义与界面是对应的,可以从这里得知各个组以及控件的name属性。如果后续还想把自定义的行为加入原生Ribbon中,或者把原生行为加到自定义的Ribbon中,也是一样的写法,注意name写对即可。

8.无法正确显示菜单的终极解决方案

1.如果不管怎么改,菜单显示始终有问题,建议直接删除appdata下的临时菜单文件,然后再启动ZW3D试试,临时菜单文件夹默认在:

C:\Users\Administrator\AppData\Roaming\ZWSOFT\ZW3D\ZW3D 2025\custom\profiles

附件

本章涉及的菜单文件如下

链接:

提取码:tj1u

关于ZW3D二开问题咨询与合作

posted @   张永全-PLM顾问  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示