1. 概述
CATPathElementAgent是 CATIA CAA 二次开发中一个核心的对话框代理类,主要用于在三维查看器中交互式地选择元素。它是实现用户与三维几何场景(如产品结构、点、线、面等)进行交互的基础。
2. 核心功能与方法
2.1 创建实例
通过构造函数创建代理实例。建议为其指定一个具有明确意义的唯一标识符。
CATPathElementAgent* _pSelectObjectEleAgent = new CATPathElementAgent("SelectNeedMoveProduct");
2.2 设置选择过滤器
这是控制代理能选择何种对象的关键,主要有两种方式:
a) 按几何维度过滤
在构造函数中直接指定要选择的几何元素的维度,这是一种快速过滤方法。
// 选择面(二维几何)
_MyAgentFace = new CATPathElementAgent("Surface", CATIMfBiDimResult::ClassName(), CATDlgEngRepeat);
常见的维度接口:
CATIMfZeroDimResult: 点(0维)CATIMfMonoDimResult: 线(1维)CATIMfBiDimResult: 面(2维)CATIMfTriDimResult: 体(3维)CATIMfInfiniteResult: 无限元素(如平面)
b) 按特定接口类型过滤
通过 AddElementType或 SetElementType方法,指定元素必须实现的接口类型。这种方式更精确,可以灵活组合。
-
选择特定几何类型:
_pSelectObjectEleAgent->AddElementType(CATIGSMPoint::ClassName()); // 点 _pSelectObjectEleAgent->AddElementType(CATIGSMLine::ClassName()); // 线 _pSelectObjectEleAgent->AddElementType(CATIGSMPlane::ClassName()); // 平面 -
选择产品对象:
_pSelectObjectEleAgent->SetElementType(CATIProduct::ClassId()); // 产品 -
允许多种类型:可以多次调用
AddElementType来允许选择多种不同类型的对象。_pSelectObjectEleAgent->AddElementType(CATIProduct::ClassId()); _pSelectObjectEleAgent->AddElementType(CATISurface::ClassName());
2.3 设置代理行为
通过 SetBehavior方法组合不同的标志位,定义代理的交互反馈模式。
_pSelectObjectEleAgent->SetBehavior(
CATDlgEngRepeat | // 允许重复选择,无需取消后重新激活命令
CATDlgEngWithPSOHSO | // 鼠标悬停时高亮可选对象(PSO),选中后保持高亮(HSO)
CATDlgEngWithPrevaluation | // 进行预评估,确保选择的有效性
CATDlgEngWithCSO | // 在选择时创建临时图形(CSO),例如绘制预览线
CATDlgEngWithUndo // 支持撤销操作
);
2.4 获取选择结果
这是两个关键方法的区别,对于后续操作至关重要:
| 方法 | 返回值 | 获取内容 | 主要用途 |
|---|---|---|---|
GetElementValue() |
CATBaseUnknown* |
用户直接选择的单个对象本身 | 直接操作该对象(如获取几何数据、属性) |
GetValue() |
CATPathElement* |
从文档根节点到所选对象的完整结构路径 | 需要了解对象在产品结构中的上下文关系 |
-
使用
GetElementValue(最常见):CATBaseUnknown* pSelectedObject = _pSelectObjectEleAgent->GetElementValue(); if (pSelectedObject != NULL) { // 查询具体接口,如 CATIProduct CATIProduct* pProduct = NULL; HRESULT hr = pSelectedObject->QueryInterface(IID_CATIProduct, (void**)&pProduct); if (SUCCEEDED(hr)) { // 使用 pProduct 进行操作... pProduct->Release(); // 务必释放! } } -
使用
GetValue(需要路径信息时):CATPathElement* pPath = _pSelectObjectEleAgent->GetValue(); if (pPath != NULL) { // 操作路径... pPath->Release(); // 务必释放! }
3. 集成到状态机命令
CATIA 的交互命令通常基于状态机模型。CATPathElementAgent需要被集成到状态机中才能工作。
- 创建或获取状态:
CATDialogState *pInitialState = GetInitialState("请选择产品");
- 将代理添加到状态:一个状态可以包含多个代理。
pInitialState->AddDialogAgent(_pSelectObjectEleAgent);
- 添加状态转换:定义当代理被成功赋值(用户做出有效选择)后,状态机如何跳转以及执行什么动作。
AddTransition(
pInitialState, // 来源状态
pNextState, // 目标状态(或 NULL 结束命令)
IsOutputSetCondition(_pSelectObjectEleAgent), // 触发条件:代理输出被设置
Action((ActionMethod) &MyCmd::ActionAfterSelection) // 触发的回调函数
);
4. 完整代码流程示例
下面的代码片段展示了在一个状态命令中集成 CATPathElementAgent的典型流程:
// 1. 创建代理
_pSelectAgent = new CATPathElementAgent("MySelectionAgent");
if (_pSelectAgent != NULL) {
// 2. 设置过滤器(例如,只选产品)
_pSelectAgent->AddElementType(CATIProduct::ClassId());
// 3. 设置行为
_pSelectAgent->SetBehavior(CATDlgEngRepeat | CATDlgEngWithPSOHSO);
}
// 4. 集成到状态机
CATDialogState *pState = GetInitialState("InitialState");
pState->AddDialogAgent(_pSelectAgent);
// 5. 定义状态转换
AddTransition(pState, NULL,
IsOutputSetCondition(_pSelectAgent),
Action((ActionMethod) &MyCommand::OnSelectionMade));
// ... 在回调函数中处理选择结果
void MyCommand::OnSelectionMade() {
CATBaseUnknown* pSelected = _pSelectAgent->GetElementValue();
if (pSelected != NULL) {
// ... 处理所选对象
}
}
5. 进阶用法与最佳实践
5.1 创建通用选择函数
为了提高代码复用性,可以创建一个通用的函数来初始化和配置代理。
void MyStateCommand::SetupSelectionAgent(CATPathElementAgent*& agent,
const char* agentId,
IID iFilterInterface,
CATDialogState* state,
ActionMethod callback) {
agent = new CATPathElementAgent(agentId);
agent->AddElementType(iFilterInterface);
agent->SetBehavior(CATDlgEngRepeat | CATDlgEngWithPSOHSO);
state->AddDialogAgent(agent);
AddTransition(state, state,
IsOutputSetCondition(agent),
Action((ActionMethod) callback));
}
5.2 内存管理
对象释放:通过
GetElementValue或GetValue获得的接口指针,在使用完毕后必须调用Release()方法释放。代理销毁:在命令的析构函数中,应调用代理的
RequestDelayedDestruction()方法以确保其被安全销毁。
5.3 错误处理
在选择操作前后,应添加适当的检查,例如检查获取的指针是否为 NULL,以及 QueryInterface是否成功。
希望这份详细的文档能帮助你全面掌握 CATPathElementAgent的使用。