Creating an Interruptible Task-使用 CATIProgressTask、CATIProgressTaskUI 与 CATTaskController
摘要
本示例教程学习要点
CAAAfrProgressTask 示例程序
- 程序功能说明
- 程序运行方式
- 源码文件位置
操作步骤
内容小结
参考资料
本用例学习内容
部分任务执行耗时较长,此时搭配进度展示界面会十分实用。同时,赋予终端用户终止任务的权限也很有必要。本文将介绍如何通过达索组件实现进度展示与任务控制功能。你需要完成以下操作:
- 实现 CATIProgressTask 接口以执行业务任务,并借助 CATIProgressTaskUI 接口管控交互界面;
- 调用 CATTaskController 类来启动任务。
CAAAfrProgressTask 示例
CAAAfrProgressTask 是 CAAApplicationFrame.edu 框架下的示例,用于演示应用框架的各项功能。
CAAAfrProgressTask 功能说明
本示例模拟一个耗时较长的执行流程。该任务共分为 50 个步骤,每个步骤都会执行以下代码:
for ( int j= 0 ; j<= 5000000 ; j++)
{
double k = 24.25 * (double) j ;
}
流程进度由达索系统组件进行展示,该组件会弹出如下对话框:
图 1:用户界面

- 对话框标题
- 左上角代表当前任务的图标
- 任务所处理对象的名称
- 进度条上方的说明文字
- 三种进度展示形式
- 进度条
- 任务已完成百分比
- 剩余预估时间
- 用于终止流程的取消按钮(该按钮为可选配置)
该任务通过交互式命令启动,此命令已添加至 CAAGeometry 文档的 CAA V5 几何分析工作台中。该命令命名为进度任务,分别设置在分析菜单栏与数学分析工具栏内。
图 2:数学分析工具栏


- 勾选可中断任务单选按钮后,进度条对话框中将显示取消按钮(见图 1)。
- 终端用户点击计算按钮,即可启动任务。
运行 CAAAfrProgressTask 示例
如需了解本示例的详细启动步骤,请查阅 CAAGeometry 示例 文档中「如何运行 CAAGeometry 示例」章节。具体操作流程如下:
启动 CATIA 软件,待程序加载完成后:
- 点击开始菜单,依次选择基础架构,再点击 CAA V5:几何分析。
- 启动进度任务命令,调出可中断任务对话框:
-
- 方式一:在数学分析工具栏中点击对应按钮
- 方式二:打开分析菜单,选择进度任务
- 点击计算
弹出计算对话框,此时无取消按钮,等待任务执行完毕。 - 在可中断任务对话框中勾选可中断任务选项。
- 点击计算
弹出带有取消按钮的计算对话框,在任务结束前点击取消。 - 再次点击计算
弹出带取消按钮的计算对话框,等待任务执行完毕。 - 点击可中断任务对话框中的关闭按钮。
查找 CAAAfrProgressTask 相关代码
- Windows 系统路径:安装根目录 \CAAApplicationFrame.edu\CAAAfrProgressTask.m\
- Unix 系统路径:安装根目录 / CAAApplicationFrame.edu/CAAAfrProgressTask.m/
分步说明
- 创建交互命令
- 实现 CATIProgressTask 接口
创建交互命令
- 头文件
- 源文件
- 本地化资源文件
头文件
// 对话框框架
#include "CATDlgDialog.h" // 用于继承 CATDlgDialog 类
// 对话框框架
class CATDlgCheckButton;
// 应用框架
class CATFrmEditor;
class CAAAfrProgressTaskSampleCmd : public CATDlgDialog
{
...
DeclareResource(CAAAfrProgressTaskSampleCmd, CATDlgDialog);
public:
// 构造函数
CAAAfrProgressTaskSampleCmd();
// 析构函数
virtual ~CAAAfrProgressTaskSampleCmd();
...
private:
// 计算按钮点击响应函数
void ClickCompute(CATCommand *iPublishingCommand,
CATNotification *iNotification,
CATCommandClientData iUsefulData);
// 关闭按钮点击响应函数
void ClickClose(CATCommand *iPublishingCommand,
CATNotification *iNotification,
CATCommandClientData iUsefulData);
// 编辑器关闭回调函数
void EditorClose (CATCallbackEvent iEvent,
void *iFrom,
CATNotification *iNotification,
CATSubscriberData iData,
CATCallback iCallBack );
// 拷贝构造函数(禁用)
CAAAfrProgressTaskSampleCmd(const CAAAfrProgressTaskSampleCmd &iObjectToCopy);
// 赋值运算符重载(禁用)
CAAAfrProgressTaskSampleCmd & operator = (const CAAAfrProgressTaskSampleCmd &iObjectToCopy);
private:
CATDlgCheckButton * _pInterruptTask; // 任务中断复选框
CATFrmEditor * _pEditor; // 编辑器指针
};
该头文件包含以下声明内容:
- 此类继承自 CATDlgDialog。
- DeclareResource 宏用于指定:命令类 CAAAfrProgressTaskSampleCmd 的资源存放于 CAAAfrProgressTaskSampleCmd.CATNls 文件中。若 CATDlgDialog 类也配置了资源,两类资源会进行合并加载。
- 按照常规写法,该类定义了构造函数与析构函数。
- 拷贝构造函数和赋值运算符(=)被声明为私有成员,避免编译器将其默认为公有成员。
- 两个回调函数,分别用于响应用户点击计算和关闭按钮的操作。
- 回调函数 EditorClose 用于监听编辑器关闭事件。若指针 _pEditor 所指向的编辑器正是启动当前命令的编辑器,则终止该命令。
- 一个复选框控件。
源文件
-
引入所需头文件
// 版权所有 达索系统 2002
// 本地框架
#include "CAAAfrProgressTaskSampleCmd.h"
// 对话框框架
#include "CATDlgCheckButton.h"
#include "CATDlgPushButton.h"
#include "CATDlgGridConstraints.h"
// 省略其他头文件
// 应用框架
#include "CATApplicationFrame.h"
#include "CATFrmEditor.h"
#include "CATTaskController.h"
// 省略其他头文件
// C++ 标准库
#include "iostream.h"
// 省略其他头文件 - 命令注册
该命令通过外部命令进行启动,相关代码如下:
// 省略部分代码
#include "CATCreateExternalObject.h"
CATCreateClass(CAAAfrProgressTaskSampleCmd);
// 省略部分代码CATCreateClass宏的作用是支持通过类名对该命令类进行实例化。 - 构造函数实现
// 。。。
CAAAfrProgressTaskSampleCmd::CAAAfrProgressTaskSampleCmd()
: CATDlgDialog((CATApplicationFrame::GetFrame())->GetMainWindow(),
"CAAAfrProgressTaskSampleId",
CATDlgGridLayout | CATDlgWndBtnClose )
{
// 创建任务中断复选框,并设置网格布局约束
_pInterruptTask = new CATDlgCheckButton(this, "InterruptId" );
_pInterruptTask->SetGridConstraints(0,0,1,1,CATGRID_CENTER);
// 创建计算按钮,并设置网格布局约束
CATDlgPushButton * pComputeButton = NULL ;
pComputeButton = new CATDlgPushButton(this, "ComputeButtonId" );
pComputeButton->SetGridConstraints(1,0,1,1,CATGRID_CENTER);
// 为计算按钮绑定点击回调函数
AddAnalyseNotificationCB(pComputeButton, pComputeButton->GetPushBActivateNotification(),
(CATCommandMethod)&CAAAfrProgressTaskSampleCmd::ClickCompute,
NULL);
// 绑定窗口关闭、对话框关闭事件的回调函数
AddAnalyseNotificationCB(this, this->GetWindCloseNotification(),
(CATCommandMethod)&CAAAfrProgressTaskSampleCmd::ClickClose,
NULL);
AddAnalyseNotificationCB(this, this->GetDiaCLOSENotification(),
(CATCommandMethod)&CAAAfrProgressTaskSampleCmd::ClickClose,
NULL);
// 获取当前编辑器实例
_pEditor = CATFrmEditor::GetCurrentEditor();
if ( (NULL != _pEditor) && (NULL != CATFrmLayout::GetCurrentLayout()) )
{
// 注册编辑器关闭事件的回调
::AddCallback(this,
CATFrmLayout::GetCurrentLayout(),
CATFrmEditor::EDITOR_CLOSE_ENDED(),
(CATSubscriberMethod)&CAAAfrProgressTaskSampleCmd::EditorClose,
NULL);
}
// 显示当前对话框
SetVisibility(CATDlgShow);
}
// 。。。
- 复选框,由指针
_pInterruptTask管理,供用户设置任务是否允许被中断。 - 普通按钮,由指针
pComputeButton管理,用于启动任务。
当用户执行以下操作时,会触发 ClickClose 回调方法:
- 点击对话框关闭按钮:触发
GetDiaCLOSENotification通知。 - 点击窗口关闭(Windows 系统为窗口右上角叉号,Unix 系统为在标题栏点击鼠标右键):触发
GetWindCloseNotification通知。
最后,我们注册回调函数以监听编辑器关闭事件。该通知由当前布局对象(会话期间为单例对象)发出。
-
析构函数相关说明
{
_pInterruptTask = NULL ;
if ( (NULL != _pEditor) && ( NULL != CATFrmLayout::GetCurrentLayout()) )
{
::RemoveSubscriberCallbacks(this,CATFrmLayout::GetCurrentLayout());
}
_pEditor = NULL ;
}
- ClickCompute 方法:
CATNotification * iNotification,
CATCommandClientData iUsefulData)
{
CATTaskController Task ;
CATIProgressTask * pIProgressTask = NULL ;
HRESULT rc = QueryInterface(IID_CATIProgressTask,(void**)& pIProgressTask);
if ( SUCCEEDED(rc) && (NULL != _pInterruptTask ) )
{
if ( CATDlgCheck == _pInterruptTask->GetState() )
{
Task.Schedule(pIProgressTask,TRUE,NULL);
}else
{
Task.Schedule(pIProgressTask,FALSE,NULL);
}
pIProgressTask->Release();
pIProgressTask = NULL ;
}
}
- CATIProgressTask 接口指针,由 pIProgressTask 引用。在当前场景中,命令类自身实现了该接口,因此对自身执行接口查询(QueryInterface)操作。
- 布尔值,用于标识是否显示取消(Cancel)按钮。本场景中,_pInterruptTask 复选框的状态存储了用户的选择。
- 作为 PerformTask 方法输入数据的参数(此处为 NULL)。
- ClickClose 方法:
void CAAAfrProgressTaskSampleCmd::ClickClose(CATCommand * iPublishingCommand,
CATNotification * iNotification,
CATCommandClientData iUsefulData)
{
SetVisibility(CATDlgHide);
RequestDelayedDestruction();
}
RequestDelayedDestruction 用于销毁当前命令对象。
- EditorClose 方法:
void CAAAfrProgressTaskSampleCmd::EditorClose(CATCallbackEvent iEvent,
void * iFrom,
CATNotification * iNotification,
CATSubscriberData iClientData,
CATCallback iCallBack )
{
if ( _pEditor == iFrom )
{
// 取消本类所有订阅消息回调
::RemoveSubscriberCallbacks(this,CATFrmLayout::GetCurrentLayout());
// 自销毁命令对象
RequestDelayedDestruction();
_pEditor = NULL ;
}
}
当编辑器关闭(即对应文档被关闭)时,布局管理器会发送通知消息,消息发布源为该编辑器;入参iFrom指向即将关闭的编辑器。倘若该编辑器与启动当前命令的编辑器是同一个实例,则需要销毁本命令对象。
-
NLS 资源文件:
- 对话框标题与内嵌控件标题配置:
Title ="Interruptible Task" ComputeButtonId.Title="Compute" ; InterruptId.Title ="Interruptible Task" ; ...
- 鼠标悬停在对话框上时,状态栏显示的帮助提示信息:
... Help = "Dialog box which creates an interruptible task "; ...
- 点击问号图标选中对话框控件时,气泡弹窗展示的详细帮助信息:
... InterruptId.LongHelp ="Check if the task is interruptible or not" ; ComputeButtonId.LongHelp ="Launch the task. It is interruptible if the previous button is checked" ; ...
- 鼠标悬浮在对话框控件上时,气泡弹窗显示的简短帮助信息:
... InterruptId.ShortHelp ="Check if the task is interruptible or not" ; ComputeButtonId.ShortHelp ="Launch the task" ; ...
- 鼠标悬停在对话框控件上时,状态栏所显示的帮助提示:
... InterruptId.Help ="Check if the task is interruptible or not" ; ComputeButtonId.Help ="Launch the task" ; ...
实现 CATIProgressTask 接口
- 在头文件中声明 CATIProgressTask 接口的各个方法
- 在源文件中添加所需头文件包含
- 编写 PerformTask(任务执行)方法代码
- 编写 GetCatalogName(获取资源目录名)方法代码
- 编写 GetIcon(获取图标)方法代码
- 修改 CAAAfrProgressTaskSampleCmd.CATNls 多语言资源文件
- 将该命令声明为组件
- 在头文件中声明 CATIProgressTask 接口的方法
class CATIProgressTaskUI ;
class CAAAfrProgressTaskSampleCmd : public CATDlgDialog
{
...
public :
...
virtual HRESULT PerformTask (CATIProgressTaskUI * iUI, void * iUserData);
virtual HRESULT GetCatalogName (CATString * oCatalogName);
virtual HRESULT GetIcon (CATString * oIcon) ;
...
}
以上便是 CATIProgressTask 接口 的三个接口函数。
- 添加所需头文件:
// 对话框框架头文件
#include "CATMsgCatalog.h"
// 应用框架头文件
#include "CATIProgressTaskUI.h"
- 编写 PerformTask 方法
HRESULT CAAAfrProgressTaskSampleCmd::PerformTask (CATIProgressTaskUI * iUI, void * iUserData)
{
if ( NULL == iUI ) return E_FAIL ;
int min = 1 ;
int max = 50 ;
iUI->SetRange(min,max);
for ( int i= min ; i <= max ; i++)
{
iUI->SetProgress(i);
CATUnicodeString usMessage ;
CATUnicodeString usParam[1] ;
usParam[0].BuildFromNum(i);
usMessage = CATMsgCatalog::BuildMessage("CAAAfrProgressTaskSampleCmd",
"ProgressTaskUI.CommentRuntime",usParam,1,
"Step ...");
iUI->SetComment(usMessage);
// 步骤耗时模拟开始
for ( int j= 0 ; j<= 5000000 ; j++)
{
double k = 24.25 * (double) j ;
}
// 步骤耗时模拟结束
CATBoolean interrupt ;
if ( S_OK != iUI->IsInterrupted(&interrupt) || (TRUE == interrupt) )
{
return E_FAIL ;
}
}
return S_OK ;
}
SetRange方法设定进度区间范围。- 进度条、预估剩余时间与完成百分比:由
SetProgress方法实现刷新。 - 进度条上方的说明文字:先用
BuildMessage拼接多语言(NLS)文本,再通过SetComment更新显示内容。
第i步...,其中 i 代表当前步骤序号。IsInterrupted方法返回TRUE;一旦任务被中断,本方法返回E_FAIL,进度对话框随之关闭。- 编写 GetCatalogName 方法
{
if ( NULL == oCatalogName ) return E_FAIL ;
*oCatalogName = CATString("CAAAfrProgressTaskSampleCmd");
return S_OK ;
}
- 编写 GetIcon 方法
{
if ( NULL == oIcon ) return E_FAIL ;
*oIcon = CATString("I_CAAProgressClock");
return S_OK ;
}
I_CAAProgressClock.bmp存放于 CAAApplicationFrame.edu 工程路径下:CNext/resources/graphic/icons/normal目录中。-
修改 CAAAfrProgressTaskSampleCmd.CATNls 资源文件
ProgressTaskUI.ObjectName = "Model";
ProgressTaskUI.Comment = "Step ..."; // 本示例未使用
Step ...不会被调用。每一步的提示内容依靠CommentRuntime关键字拼接生成,占位参数用于填入当前步骤序号。- 将命令声明为组件
实现接口的类对象必须定义为组件。
class CAAAfrProgressTaskSampleCmd : public CATDlgDialog
{
CATDeclareClass;
...
public :
...
CATDeclareClass宏用于声明:CAAAfrProgressTaskSampleCmd类隶属于组件。
CATImplementClass(CAAAfrProgressTaskSampleCmd, Implementation, CATCommand, CATNull);
CATImplementClass宏配合Implementation关键字,声明CAAAfrProgressTaskSampleCmd是组件主类,并基于 OM 机制继承自CATCommand。
#include <TIE_CATIProgressTask.h>
TIE_CATIProgressTask(CAAAfrProgressTaskSampleCmd);
TIE_CATIProgressTask宏,标明CAAAfrProgressTaskSampleCmd类实现了CATIProgressTask接口。
CAAApplicationFrame.edu.dico存放在框架目录:CAAApplicationFrame.edu/CNext/code/dictionary,文件内添加如下配置行:CAAAfrProgressTaskSampleCmd CATIProgressTask libCAAAfrProgressTask
...
简要总结
CATIProgressTask接口,任务通过CATTaskController类实例启动运行。References
| [1] | Object Modeler Component and Implementation Inheritance |

浙公网安备 33010602011771号