本文介绍 CAA 二次开发中使用声明文件创建命令的方法,为创建命令提供一种更简便的方式。
目录
1、简介
首先,我先介绍一下本文涉及到的一些术语。
CommandHeader 命令头,我们在 CATIA 界面看到的命令实际上是由此命令头展示的,只有点击命令图标,相应的命令才会加载。
App 应用模块,如零件设计模块(Part Design),在 CAA 接口中对应于 Workbench 。
Model 数据模型,如产品、零件、草图等。一个数据模型可以被不同的应用模块操作,例如在零件节点中,我们可以使用零件设计模块、曲面设计模块等,在 CAA 接口中对应于 Workshop 。
Addin 命令插件,大多数时候 CAA 开发的命令都是通过命令插件显示在 CATIA 界面的。插件分为三种类型:通用命令插件(General Addin)、模型命令插件(Model Addin)、模块命令插件(App Addin)。
2、为什么要使用声明文件创建命令
在 2.7 新建 Component 中介绍了通过自定义组件实现 CATIAfrGeneralWksAddin 接口的方式创建命令,组件中主要提供以下两个接口函数的实现:
public virtual void CreateCommands() = 0
public virtual CATCmdContainer* CreateToolbars() = 0
但是 CATIAfrGeneralWksAddin 是一个通用命令插件接口,组件实现此接口创建的命令会显示在所有模块下,如果定制开发的功能比较多,界面就比较混乱了,如果只希望二次开发的命令按功能分别显示在特定的应用模块下,就需要实现特定的接口,例如将命令显示在工程图应用中,需让组件实现 CATIDrwAddin 接口,然而并不是所有的应用都有相应的 Addin 接口,自己写 Addin 接口又比较复杂。
因此,本文介绍如何使用声明文件创建命令。
声明文件是一个以 afr 为扩展名的 XML 文件,通过文件所在的路径来指定数据模型和应用模块信息,下文分别介绍通过声明文件创建各种命令插件以及应用模块的方法。
开始之前,首先在对应的框架(如 TestFrame)的依赖文件 IdentityCard.xml 中添加以下内容
<toolPrerequisite name="MkDAfrTool"/>
3、创建通用命令插件(General Addin)
通用命令插件会显示在所有模块下,创建步骤如下:
3.1 创建模块
在对应的框架(如 TestFrame)下创建一个模块(如 TestGlobalD),类型选择 Resource,如 图1

完成后修改模块的 Imakefile.mk 依赖文件,添加如下内容:
BUILT_OBJECT_TYPE = RUNTIME DATA
SCRAMBLING_KEY = 2
3.2 创建指定路径
创建指定目录路径,如 图2

- TestFrame 框架所在目录
- TestGlobalD.m 模块所在目录
- src 创建模块时自动创建的目录
- resources 固定名称的目录
- ApplicationFrame 固定名称的目录
- AfrWorkshop 固定名称的目录,指数据模型
- Global 特定名称目录,指通用命令
- AfrAddin 固定名称的目录,指命令插件
3.3 创建声明文件
在上述 AfrAddin 目录中创建声明文件 TestGlobalD.afr (文件名建议与模块名一致),文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<Styles xmlns:syp="http://www.3ds.com/xsd/SYP">
<Template syp:name="TestGlobalDHeaders" Target="CATCmdHeadersList">
<CATCmdHeadersList>
<CATCommandHeader ID="TestGlobalDCmd_1" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestGlobalHeaderD" Available="1"/>
<CATCommandHeader ID="TestGlobalDCmd_2" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestGlobalHeaderD" Available="1"/>
</CATCmdHeadersList>
</Template>
<Template syp:name="TestGlobalDAccess" Target="CATCmdAddin">
<CATCmdAddin>
<CATCmdContainer Name="TestGlobalDSection">
<CATCmdContainer Name="TestGlobalDTlb">
<CATCmdStarter Name="TestGlobalDCmd_1" Command="TestGlobalDCmd_1"/>
<CATCmdStarter Name="TestGlobalDCmd_2" Command="TestGlobalDCmd_2"/>
</CATCmdContainer>
</CATCmdContainer>
</CATCmdAddin>
</Template>
</Styles>
说明:
- 第一行声明这个文件是一个 XML 文件。
- 根节点 Styles 告诉编译器按声明文件来解析此文件。
- 第一个 Template 节点定义 CATCommandHeader 信息,类似于实现 CreateCommands() 。syp:name 属性必须为 XXXHeaders,XXX 建议与 Module 名称一致。CATCommandHeader 节点的属性与 CATAfrCommandHeader::CATCreateCommandHeader() 方法的参数对应,其他信息与示例保持一致。
- 第二个 Template 节点定义命令布局信息,类似于实现 CreateToolbars() 。syp:name 属性必须为 XXXAccess,XXX 建议与 Module 名称一致。CATCmdStarter 节点的属性与 SetAccessCommand 宏的参数对应,CATCmdContainer 节点按层级关系定义命令布局,类似于 NewAccess、SetAccessChild、SetAccessNext 宏的作用,其他信息与示例保持一致。
完成后,刷新 VS 解决方案,如 图3

3.4 创建资源文件
创建资源文件方式与实现 Addin 接口时创建命令资源的方式一致(图 4):

TestGlobalD.CATNls 内容如下:
<meta charset="UTF-8"/>
TestGlobalDSection.Title="TestGlobalDSection";
TestGlobalHeaderD.CATNls 内容如下:
<meta charset="UTF-8"/>
TestGlobalHeaderD.TestGlobalDCmd_1.Title="TestGlobalDCmd_1";
TestGlobalHeaderD.TestGlobalDCmd_1.ShortHelp="TestGlobalDCmd_1";
TestGlobalHeaderD.TestGlobalDCmd_2.Title="TestGlobalDCmd_2";
TestGlobalHeaderD.TestGlobalDCmd_2.ShortHelp="TestGlobalDCmd_2";
TestGlobalHeaderD.CATRsc 内容如下:
TestGlobalHeaderD.TestGlobalDCmd_1.Icon.Normal="I_TestCommand";
TestGlobalHeaderD.TestGlobalDCmd_2.Icon.Normal="I_TestCommand";
3.5 修改字典文件
在框架的字典文件(图 5)TestFrame.dico 中添加以下内容:
TestGlobalD CATIAfrGeneralWksAddin libTestMdl

3.6 编译运行
上述步骤正确完成后,仅实现了在界面中显示命令,要使命令有效果,需要编写相应的命令实现(具体参考 CAA 二次开发 —— 创建项目)。
然后编译运行,效果如 图6

4、创建模块命令插件(App Addin)
模块命令插件会显示在指定模块下,创建步骤与通用命令插件类似,具体如下:
4.1 创建模块
在对应的框架(如 TestFrame)下创建一个模块(如 TestAddinD),类型选择 Resource,如 图7

完成后修改模块的 Imakefile.mk 依赖文件,添加如下内容:
BUILT_OBJECT_TYPE = RUNTIME DATA
SCRAMBLING_KEY = 2
4.2 创建指定路径
创建指定目录路径,如 图8

- TestFrame 框架所在目录
- TestAddinD.m 模块所在目录
- src 创建模块时自动创建的目录
- resources 固定名称的目录
- ApplicationFrame 固定名称的目录
- AfrWorkshop 固定名称的目录,指数据模型
- PrtWks 特定名称目录,指零件模型
- AfrWorkbench 固定名称的目录,指应用模块
- PrtCfg 特定名称目录,指零件设计模块
- AfrAddin 固定名称的目录,指命令插件
上述路径中,PrtWks 和 PrtCfg 分别表示零件模型和零件模块,如果要将命令添加到其他的模型或模块,需要获取其名称,可以通过 CATApplicationFrame 对象进行获取,以下是示例代码:
CATApplicationFrame* pAppFrame = CATApplicationFrame::GetFrame();
if (NULL != pAppFrame)
{
cout << "CurrentWorkshop = " << pAppFrame->GetCurrentWorkshop() << endl;
cout << "CurrentWorkbench = " << pAppFrame->GetCurrentWorkbench() << endl;
}
将上述代码加到命令中,然后启动客户端打开相应的模型或模块,执行命令并查看输出(图 9),其中 Workshop 对应模型,Workbench 对应模块:

4.3 创建声明文件
在上述 AfrAddin 目录中创建声明文件 TestAddinD.afr (文件名建议与模块名一致),文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<Styles xmlns:syp="http://www.3ds.com/xsd/SYP">
<Template syp:name="TestAddinDHeaders" Target="CATCmdHeadersList">
<CATCmdHeadersList>
<CATCommandHeader ID="TestAddinDCmd_1" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAddinHeaderD" Available="1"/>
<CATCommandHeader ID="TestAddinDCmd_2" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAddinHeaderD" Available="1"/>
</CATCmdHeadersList>
</Template>
<Template syp:name="TestAddinDAccess" Target="CATCmdAddin">
<CATCmdAddin>
<CATCmdContainer Name="TestAddinDSection">
<CATCmdContainer Name="TestAddinDTlb">
<CATCmdStarter Name="TestAddinDCmd_1" Command="TestAddinDCmd_1"/>
<CATCmdStarter Name="TestAddinDCmd_2" Command="TestAddinDCmd_2"/>
</CATCmdContainer>
</CATCmdContainer>
</CATCmdAddin>
</Template>
</Styles>
完成后,刷新 VS 解决方案,如 图10

4.4 创建资源文件
创建资源文件方式与实现 Addin 接口时创建命令资源的方式一致(图 11):

TestAddinD.CATNls 内容如下:
<meta charset="UTF-8"/>
TestAddinDSection.Title="TestAddinDSection";
TestAddinHeaderD.CATNls 内容如下:
<meta charset="UTF-8"/>
TestAddinHeaderD.TestAddinDCmd_1.Title="TestAddinDCmd_1";
TestAddinHeaderD.TestAddinDCmd_1.ShortHelp="TestAddinDCmd_1";
TestAddinHeaderD.TestAddinDCmd_2.Title="TestAddinDCmd_2";
TestAddinHeaderD.TestAddinDCmd_2.ShortHelp="TestAddinDCmd_2";
TestAddinHeaderD.CATRsc 内容如下:
TestAddinHeaderD.TestAddinDCmd_1.Icon.Normal="I_TestCommand";
TestAddinHeaderD.TestAddinDCmd_2.Icon.Normal="I_TestCommand";
4.5 编译运行
编译运行,效果如 图12

5、创建模型命令插件(Model Addin)
模型命令插件会显示在指定模型的所有模块下,创建步骤与通用命令插件类似,具体如下:
5.1 创建模块
在对应的框架(如 TestFrame)下创建一个模块(如 TestModelD),类型选择 Resource,如 图13

完成后修改模块的 Imakefile.mk 依赖文件,添加如下内容:
BUILT_OBJECT_TYPE = RUNTIME DATA
SCRAMBLING_KEY = 2
5.2 创建指定路径
创建指定目录路径,如 图14

- TestFrame 框架所在目录
- TestModelD.m 模块所在目录
- src 创建模块时自动创建的目录
- resources 固定名称的目录
- ApplicationFrame 固定名称的目录
- AfrWorkshop 固定名称的目录,指数据模型
- PrtWks 特定名称目录,指零件模型
- AfrAddin 固定名称的目录,指命令插件
上述路径中,PrtWks 表示零件模型,如果要将命令添加到其他的模型,需要获取其名称,具体方法请参考第 4.2 节。
5.3 创建声明文件
在上述 AfrAddin 目录中创建声明文件 TestModelD.afr (文件名建议与模块名一致),文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<Styles xmlns:syp="http://www.3ds.com/xsd/SYP">
<Template syp:name="TestModelDHeaders" Target="CATCmdHeadersList">
<CATCmdHeadersList>
<CATCommandHeader ID="TestModelDCmd_1" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestModelHeaderD" Available="1"/>
<CATCommandHeader ID="TestModelDCmd_2" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestModelHeaderD" Available="1"/>
</CATCmdHeadersList>
</Template>
<Template syp:name="TestModelDAccess" Target="CATCmdAddin">
<CATCmdAddin>
<CATCmdContainer Name="TestModelDSection">
<CATCmdContainer Name="TestModelDTlb">
<CATCmdStarter Name="TestModelDCmd_1" Command="TestModelDCmd_1"/>
<CATCmdStarter Name="TestModelDCmd_2" Command="TestModelDCmd_2"/>
</CATCmdContainer>
</CATCmdContainer>
</CATCmdAddin>
</Template>
</Styles>
完成后,刷新 VS 解决方案,如 图15

5.4 创建资源文件
创建资源文件方式与实现 Addin 接口时创建命令资源的方式一致(图 16):

TestModelD.CATNls 内容如下:
<meta charset="UTF-8"/>
TestModelDSection.Title="TestModelDSection";
TestModelHeaderD.CATNls 内容如下:
<meta charset="UTF-8"/>
TestModelHeaderD.TestModelDCmd_1.Title="TestModelDCmd_1";
TestModelHeaderD.TestModelDCmd_1.ShortHelp="TestModelDCmd_1";
TestModelHeaderD.TestModelDCmd_2.Title="TestModelDCmd_2";
TestModelHeaderD.TestModelDCmd_2.ShortHelp="TestModelDCmd_2";
TestModelHeaderD.CATRsc 内容如下:
TestModelHeaderD.TestModelDCmd_1.Icon.Normal="I_TestCommand";
TestModelHeaderD.TestModelDCmd_2.Icon.Normal="I_TestCommand";
5.5 编译运行
编译运行,效果如 图17

6、创建应用模块(App)
本节介绍如何创建一个新的应用模块,可以在 3D Compass 中点击新模块显示命令,具体如下:
6.1 创建模块
在对应的框架(如 TestFrame)下创建一个模块(如 TestAppD),类型选择 Resource,如 图18

完成后修改模块的 Imakefile.mk 依赖文件,添加如下内容:
BUILT_OBJECT_TYPE = RUNTIME DATA
SCRAMBLING_KEY = 2
6.2 创建指定路径
创建指定目录路径,如 图19

- TestFrame 框架所在目录
- TestAppD.m 模块所在目录
- src 创建模块时自动创建的目录
- resources 固定名称的目录
- ApplicationFrame 固定名称的目录
- AfrWorkshop 固定名称的目录,指数据模型
- PrtWks 特定名称目录,指零件模型
- AfrWorkbench 固定名称的目录,指应用模块
- TestAppD 特定名称目录,指新建模块
上述路径中,PrtWks 表示零件模型,如果要将命令添加到其他的模型,需要获取其名称,具体方法请参考第 4.2 节。
6.3 创建声明文件
在上述 TestAppD 目录中创建声明文件 TestAppD.afr (文件名建议与模块名一致),文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<Styles xmlns:syp="http://www.3ds.com/xsd/SYP">
<Template syp:name="TestAppDInterface" Target="CATCmdInterface">
<!-- Define here the interface to extend your app -->
<CATCmdInterface/>
</Template>
<Template syp:name="TestAppDHeaders" Target="CATCmdHeadersList">
<!-- Define here the command headers of your app -->
<CATCmdHeadersList>
<CATCommandHeader ID="TestAppDCmd_1" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAppHeaderD" Available="1"/>
<CATCommandHeader ID="TestAppDCmd_2" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAppHeaderD" Available="0"/>
<CATCommandHeader ID="TestAppDCmd_3" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAppHeaderD" Available="0"/>
<CATCommandHeader ID="TestAppDCmd_4" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAppHeaderD" Available="1"/>
<CATCommandHeader ID="TestAppDCmd_5" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAppHeaderD" Available="1"/>
<CATCommandHeader ID="TestAppDCmd_6" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAppHeaderD" Available="1"/>
<CATCommandHeader ID="TestAppDCmd_7" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAppHeaderD" Available="1"/>
<CATCommandHeader ID="TestAppDCmd_8" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAppHeaderD" Available="1"/>
<CATCommandHeader ID="TestAppDCmd_9" ClassName="TestCommandCmd" SharedLibraryName="TestMdl" ResourceFile="TestAppHeaderD" Available="1"/>
</CATCmdHeadersList>
</Template>
<Template syp:name="TestAppDAccess" Target="CATCmdWorkbench">
<!-- Define here the layout of your commands. -->
<CATCmdWorkbench Name="TestAppD">
<CATCmdContainer Name="TestAppDSection">
<CATCmdContainer Name="TestAppDTlb_1">
<CATCmdStarter Name="TestAppDCmd_1" Command="TestAppDCmd_1"/>
<CATCmdStarter Name="TestAppDCmd_2" Command="TestAppDCmd_2"/>
<CATCmdStarter Name="TestAppDCmd_3" Command="TestAppDCmd_3"/>
</CATCmdContainer>
<CATCmdContainer Name="TestAppDTlb_2">
<CATCmdStarter Name="TestAppDCmd_4" Command="TestAppDCmd_4"/>
<CATCmdStarter Name="TestAppDCmd_5" Command="TestAppDCmd_5"/>
</CATCmdContainer>
<CATCmdContainer Name="TestAppDTlb_3">
<CATCmdStarter Name="TestAppDCmd_6" Command="TestAppDCmd_6"/>
<CATCmdContainer Name="TestAppDFlyout">
<CATCmdStarter Name="TestAppDCmd_7" Command="TestAppDCmd_7"/>
<CATCmdStarter Name="TestAppDCmd_8" Command="TestAppDCmd_8"/>
<CATCmdStarter Name="TestAppDCmd_9" Command="TestAppDCmd_9"/>
</CATCmdContainer>
</CATCmdContainer>
</CATCmdContainer>
</CATCmdWorkbench>
</Template>
</Styles>
说明:
- 相较于命令插件,创建应用模块的声明文件中多了一个 Template 节点,注意节点的 syp:name 属性应为 XXXInterface,其中 XXX 应为新建的模块名称即 TestAppD,其他部分与示例保持一致即可。
- 声明文件中定义了较多的命令,并展示了将命令放到不同级别的容器中,后面可以注意运行效果。
完成后,刷新 VS 解决方案,如 图20

6.4 创建资源文件
创建资源文件方式与实现 Addin 接口时创建命令资源的方式一致(图 21):

TestAppD.CATNls 内容如下:
<meta charset="UTF-8"/>
TestAppDSection.Title="TestAppDSection";
TestAppHeaderD.CATNls 内容如下:
<meta charset="UTF-8"/>
TestAppHeaderD.TestAppDCmd_1.Title="TestAppDCmd_1";
TestAppHeaderD.TestAppDCmd_1.ShortHelp="TestAppDCmd_1";
TestAppHeaderD.TestAppDCmd_2.Title="TestAppDCmd_2";
TestAppHeaderD.TestAppDCmd_2.ShortHelp="TestAppDCmd_2";
TestAppHeaderD.TestAppDCmd_3.Title="TestAppDCmd_3";
TestAppHeaderD.TestAppDCmd_3.ShortHelp="TestAppDCmd_3";
TestAppHeaderD.TestAppDCmd_4.Title="TestAppDCmd_4";
TestAppHeaderD.TestAppDCmd_4.ShortHelp="TestAppDCmd_4";
TestAppHeaderD.TestAppDCmd_5.Title="TestAppDCmd_5";
TestAppHeaderD.TestAppDCmd_5.ShortHelp="TestAppDCmd_5";
TestAppHeaderD.TestAppDCmd_6.Title="TestAppDCmd_6";
TestAppHeaderD.TestAppDCmd_6.ShortHelp="TestAppDCmd_6";
TestAppHeaderD.TestAppDCmd_7.Title="TestAppDCmd_7";
TestAppHeaderD.TestAppDCmd_7.ShortHelp="TestAppDCmd_7";
TestAppHeaderD.TestAppDCmd_8.Title="TestAppDCmd_8";
TestAppHeaderD.TestAppDCmd_8.ShortHelp="TestAppDCmd_8";
TestAppHeaderD.TestAppDCmd_9.Title="TestAppDCmd_9";
TestAppHeaderD.TestAppDCmd_9.ShortHelp="TestAppDCmd_9";
TestAppHeaderD.CATRsc 内容如下:
TestAppHeaderD.TestAppDCmd_1.Icon.Normal="I_TestCommand";
TestAppHeaderD.TestAppDCmd_2.Icon.Normal="I_TestCommand";
TestAppHeaderD.TestAppDCmd_3.Icon.Normal="I_TestCommand";
TestAppHeaderD.TestAppDCmd_4.Icon.Normal="I_TestCommand";
TestAppHeaderD.TestAppDCmd_5.Icon.Normal="I_TestCommand";
TestAppHeaderD.TestAppDCmd_6.Icon.Normal="I_TestCommand";
TestAppHeaderD.TestAppDCmd_7.Icon.Normal="I_TestCommand";
TestAppHeaderD.TestAppDCmd_8.Icon.Normal="I_TestCommand";
TestAppHeaderD.TestAppDCmd_9.Icon.Normal="I_TestCommand";
6.5 创建附加应用程序
要使新的应用模块在 3D Compass 中可见,需要使用平台管理员账户登录平台创建附加应用程序,具体如下:
- 登录平台,进入平台管理 - 成员页面,点击创建附加应用程序(图 22)

- 填写应用程序名称、类型、ID、可执行文件等信息,上传图标文件后完成创建(图 23)

6.6 编译运行
编译运行,效果如 图 24、图 25


本文根据 CAA 开发手册实际操作后编写,如果你也对 CAA 二次开发感兴趣,欢迎留言交流。