Creating Customized Command Headers-公开你的命令并管理其可用性
摘要
-
本用例学习内容
-
CAAAfrDumpCommandHeader 用例
- CAAAfrDumpCommandHeader 功能说明
- CAAAfrDumpCommandHeader 启动方法
- CAAAfrDumpCommandHeader 代码位置
-
分步实现
-
小结
-
参考文献
通过本用例您将学到
CAAAfrDumpCommandHeader 用例

CAAAfrDumpCommandHeader 用例通过创建命令头类,来管理 ** 元素统计(Element Count)** 命令的可用状态。元素统计命令会扫描当前活动的 CAAGeometry 文档,并在对话框中输出文档所包含对象的清单。该命令仅在文档非空时才有意义,否则会被设为不可用状态。元素统计命令的可用性正是由其对应的命令头进行管理的。
- 它与通过
MacDeclareHeader宏创建的命令头一样,是一个标准命令头。这一点通过使该命令头类继承自CATCommandHeader得以实现。 - 此外,它需要在文档至少包含一个对象时将命令设为可用状态,在其他情况下设为不可用状态。这一功能由
CATCommandHeader类的BecomeAvailable和BecomeUnavailable方法实现。
如何运行 CAAAfrDumpCommandHeader
- 在文件(File)菜单中,单击新建(New)
- 在弹出的 “新建” 对话框中,选择 CAAGeometry 并单击确定(OK)
- 使用 ** 基础元素(Basic Elements)工具栏中的命令,或通过插入(Insert)** 菜单中的对应命令,创建若干几何对象,例如点、直线、平面等
- 在工具(Tools)菜单中,单击元素统计(Element Count)。系统将弹出对话框,显示各类元素的数量统计信息
注意:如果文档为空,** 元素统计(Element Count)** 命令会呈灰色禁用状态,无法被触发执行。
CAAAfrDumpCommandHeader 代码位置
- Windows 平台:
InstallRootDirectory\CAAApplicationFrame.edu\CAAAfrGeometryWshop.m\ - Unix 平台:
InstallRootDirectory/CAAApplicationFrame.edu/CAAAfrGeometryWshop.m/
其中 InstallRootDirectory 为 CAA 光盘内容的安装根目录。
CAAAfrDumpCommandHeader 在 CAA 几何创建工作台中被实例化,是该工作台的组成部分。
分步实现
| 序号 | 步骤 | 实现位置 |
|---|---|---|
| 1 | 创建命令头类头文件 | LocalInterfaces |
| 2 | 声明命令头类资源 | CAAAfrDumpCommandHeader.cpp |
| 3 | 设置对应事件的回调并初始化命令可用状态 | 构造函数 |
| 4 | 实现拷贝构造函数、Clone 方法与析构函数 | CAAAfrDumpCommandHeader.cpp |
| 5 | 编写用于管理命令可用状态的回调方法 | CAAAfrDumpCommandHeader.cpp |
| 6 | 实例化命令头类 | CAAAfrGeometryWshop.m 的 CreateCommands 方法 |
| 7 | 为命令头实例分配资源 | 资源文件 |
创建命令头类
#include <CATCommandHeader.h>
...
class CAAAfrDumpCommandHeader : public CATCommandHeader
{
CATDeclareClass;
CATDeclareHeaderResources;
public:
CAAAfrDumpCommandHeader(const CATString & iHeaderName);
virtual ~CAAAfrDumpCommandHeader();
CATCommandHeader * Clone();
private:
CAAAfrDumpCommandHeader(CATCommandHeader *iHeaderToCopy);
CAAAfrDumpCommandHeader(const CAAAfrDumpCommandHeader &iObjectToCopy);
void AnalyzeFilledCB(CATCallbackEvent iPublishedEvent,
void * ipPublishingObject,
CATNotification * ipPublishNotification,
CATSubscriberData iUsefulData,
CATCallback iCallbackId);
void AnalyzeEmptyCB (CATCallbackEvent iPublishedEvent,
void * ipPublishingObject,
CATNotification * ipPublishNotification,
CATSubscriberData iUsefulData,
CATCallback iCallbackId);
private:
CAAISysCollection * _pCollection;
};
CAAAfrDumpCommandHeader 类继承自 CATCommandHeader。CATDeclareClass 宏用于声明该类属于一个 CAA 组件。CATDeclareHeaderResources 宏会插入用于管理命令头资源的相关方法。
关于必需的公有方法
- 一个以 const CATString 引用为参数的构造函数
- 析构函数
- 从 CATCommandHeader 继承而来的 Clone 方法,用于复制该命令头实例。可参考技术文章《命令头》[2] 中的 “自定义命令头类结构” 章节,其中包含 Clone 方法的完整详细说明。
关于必需的私有方法
- 一个以 CATCommandHeader 指针为参数的构造函数,专门供 Clone 方法使用。
- 另外两个构造函数在私有区域声明,且不在源文件中实现。这可以避免编译器在不知情的情况下自动将其生成为公有方法。
声明了两个回调方法 AnalyzeFilledCB 和 AnalyzeEmptyCB,分别在文档包含对象或文档为空时被调用。_pCollection 是指向文档中对象集合的指针,该指针与具体文档相关联。
声明命令头类资源
...
CATImplementClass(CAAAfrDumpCommandHeader,Implementation, CATCommandHeader, CATNull);
CATImplementHeaderResources(CAAAfrDumpCommandHeader,
CATCommandHeader,
CAAAfrDumpCommandHeader);
...
自定义命令头是一个 CAA 组件。CATImplementClass 宏将 CAAAfrDumpCommandHeader 类设为组件主类(Implementation),使其从 CATCommandHeader 进行 OM 派生 [1]。
CATImplementHeaderResources 宏与头文件中的 CATDeclareHeaderResources 宏配合使用。它表明:
- CAAAfrDumpCommandHeader 类继承自 CATCommandHeader
- 其关联的资源文件名直接使用类名,分别为 CAAAfrDumpCommandHeader.CATNls 和 CAAAfrDumpCommandHeader.CATRsc
第二个参数传入的基类名称有助于实现资源拼接。第三个参数可以设为:
- 另一个与其资源文件关联的类的类名;
- 或某个已存在的资源文件对的无后缀名称。
设置对应事件的回调并初始化命令可用状态
...
CAAAfrDumpCommandHeader::CAAAfrDumpCommandHeader(const CATString &iHeaderName)
: CATCommandHeader(iHeaderName, // 命令头 ID
"CAAAfrGeoCommands", // 命令共享库或 DLL
"CAAAfrDumpCmd", // 命令类
(void*) NULL), // 无需向命令传递参数
_pCollection(NULL)
{
... // 获取 _pCollection 指针
if (NULL != _pCollection)
{
::AddCallback(this,
_pCollection,
"CAASysCollectionEmptyNotif",
(CATSubscriberMethod)&CAAAfrDumpCommandHeader::AnalyzeEmptyCB,
NULL);
::AddCallback(this,
_pCollection,
"CAASysCollectionFilledNotif",
(CATSubscriberMethod)&CAAAfrDumpCommandHeader::AnalyzeFilledCB,
NULL);
int nbobject = 0;
_pCollection->GetNumberOfObjects(&nbobject);
if (nbobject > 1)
BecomeAvailable();
else
BecomeUnavailable();
}
else
BecomeUnavailable();
}
CAAAfrDumpCommandHeader::~CAAAfrDumpCommandHeader()
{
if (NULL != _pCollection)
{
RemoveSubscriberCallbacks(_pCollection);
_pCollection->Release();
_pCollection = NULL;
}
...
构造函数首先获取一个集合接口指针,该接口用于管理文档中的对象,具体实现与文档自身相关。当文档被创建或变为空文档时,该集合会发送一个 CAASysCollectionEmptyNotif 通知类实例。
通过全局函数 AddCallback 为这两种通知分别设置了回调。以第一次函数调用为例,其参数含义如下:
this:执行回调方法的对象_pCollection:发送通知的对象CAASysCollectionEmptyNotif:所发送通知的类名AnalyzeEmptyCB:需要被回调的方法NULL:可传递给该方法的附加数据(此处无)
构造函数最后通过集合接口指针判断文档是否为空(空文档至少包含一个对象:UI 激活对象)。根据判断结果,使用 BecomeAvailable 和 BecomeUnavailable 两个方法初始化命令的可用状态。
不要忘记在析构函数中使用 RemoveSubscriberCallbacks 方法移除订阅。
实现拷贝构造函数、Clone 方法与析构函数
...
CAAAfrDumpCommandHeader::CAAAfrDumpCommandHeader(CATCommandHeader * iHeaderToCopy)
: CATCommandHeader(iHeaderToCopy),
_pCollection(NULL)
{}
CATCommandHeader * CAAAfrDumpCommandHeader::Clone()
{
return new CAAAfrDumpCommandHeader(this);
}
CAAAfrDumpCommandHeader::~CAAAfrDumpCommandHeader()
{
if ( NULL != _pCollection)
{
RemoveSubscriberCallbacks(_pCollection);
_pCollection->Release();
_pCollection = NULL;
}
...
不要忘记在析构函数中使用 RemoveSubscriberCallbacks 方法移除相关订阅。
创建用于管理命令可用状态的回调方法
...
void CAAAfrDumpCommandHeader::AnalyzeFilledCB(CATCallbackEvent iPublishedEvent,
void * ipPublishingObject,
CATNotification * ipNotif,
CATSubscriberData iUsefulData,
CATCallback iCallbackId)
{
BecomeAvailable();
}
void CAAAfrDumpCommandHeader::AnalyzeEmptyCB (CATCallbackEvent iPublishedEvent,
void * ipPublishingObject,
CATNotification * ipNotif,
CATSubscriberData iUsefulData,
CATCallback iCallbackId)
{
BecomeUnavailable();
}
这两个方法采用回调方法的标准签名。根据接收到的不同通知,它们会简单地将命令设置为对应的可用或不可用状态。
实例化命令头类
CreateCommands 方法中调用其构造函数,并传入命令头标识符作为参数。void CAAAfrGeometryWks::CreateCommands()
{
...
new CAAAfrDumpCommandHeader("CAAAfrDumpHdr");
...
}
CAAAfrDumpHdr 是分配给该命令头的标识符。该标识符后续会用于:- 将定义好的命令启动器与该命令头关联,从而把命令添加到菜单和工具栏中
- 构建用于定义命令头资源的变量,例如菜单中显示给用户的本地化名称、工具栏上显示的图标等。
为命令头实例分配资源
- CAAAfrDumpCommandHeader.CATNls:用于可翻译的标题与帮助信息
- CAAAfrDumpCommandHeader.CATRsc:用于其他资源,例如在工具栏中显示的图标
资源通过一个键名来指定,键名由命令头类名、命令头实例标识符和资源关键字以点号分隔拼接而成。CAAAfrDumpCommandHeader.CATNls 文件中对该命令的资源定义示例如下:
CAAAfrDumpCommandHeader.CAAAfrDumpHdr.Title = "元素统计…";
CAAAfrDumpCommandHeader.CAAAfrDumpHdr.ShortHelp = "元素统计";
CAAAfrDumpCommandHeader.CAAAfrDumpHdr.Help = "文档内容";
CAAAfrDumpCommandHeader.CAAAfrDumpHdr.LongHelp = "元素统计(工具菜单)
该命令允许用户输出文档内容";
CAAAfrDumpCommandHeader.CAAAfrDumpHdr.Category = "工具";
这些资源包括:
Title

该命令在工具(Tools)菜单中显示的文本
ShortHelp

当命令位于工具栏中时,鼠标悬停其上时,在提示框中显示的命令简短帮助信息。此内容不适用于菜单栏中的命令。
Help

鼠标悬停在该命令上时,在状态栏中显示的命令帮助信息。此内容不适用于仅出现在菜单栏中的命令,但适用于同时出现在菜单栏和工具栏中的命令。
Category

与命令关联的一个属性,用于在自定义窗口的命令选项页中对命令进行排序。
LongHelp

当最终用户点击 “这是什么” 帮助按钮(I_WhatsThisP2.gif),鼠标指针变为问号形状后,再点击代表该命令的图标时,在提示框中显示的文本。此内容不适用于位于菜单栏中的命令。
CAAAfrGeometryWksHeader.CATRsc 文件中包含针对 Point 命令的如下配置:
CAAAfrDumpCommandHeader.CAAAfrDumpHdr.Icon.Normal = "I_CAAFindP2";
CAAAfrDumpCommandHeader.CAAAfrDumpHdr.LongHelpId = "CAAAfrDumpCommandHeader.CAAAfrDumpHdr";
这些是用于在工具栏中显示 “元素统计” 命令的图标文件名:
Icon.Normal

与该命令关联的图标,在命令可用时显示在工具栏中。命令不可用时显示的灰色禁用图标,是由该图标自动生成的。在 P2 界面模式下,默认状态的阴影图标、按下状态图标和焦点状态图标,也均由该常规图标自动生成。
LongHelpId
与命令关联的标识符,当该命令处于激活状态时,按下 F1 键可调用对应的命令帮助文档。
简要总结
References
| [1] | Object Modeler Component and Implementation Inheritances |
| [2] | The Command Headers |

浙公网安备 33010602011771号