类CCmdTarget是MFC类库中消息映射体系的一个
基类,是MFC处理命令消息的基础、核心。消息映射把命令或消息引导给用户为之编写的响应函数。
简介
由CCmdTarget继承的按键框架类包括:CView、CWinApp、CDocument、CWnd和CFrameWnd。如果想生成一个处理按键消息的类,可以选择其中的一个派生子类。很少需要直接从CCmdTarget派生类。
MFC为该类设计了许多成员函数和一些成员数据,基本上是为了解决消息映射问题的,而且,很大一部分是针对OLE设计的。在OLE应用中,CCmdTarget是MFC处理模块状态的重要环节,它起到了传递模块状态的作用:其构造函数获取当前模块状态,并保存在
成员变量m_pModuleState里头。
CCmdTarget有两个与消息映射有密切关系的成员函数:DispatchCmdMsg和OnCmdMsg。
类CmdTarget包括了处理沙漏形光标显示的成员函数。当某个命令的执行时间比较长时,可以显示沙漏标提示用户命令正在执行。
和消息映射类似,分派映射用于列出OLE自动的IDispatch功能。列出这个接口后,其它的应用(如VB)就能调用这个应用了。有关IDispatch接口的更详细的信息,请参阅“Win32 SDK OLE程序员参考”中的“创建IDPatch接口”和“分派接口与API函数”。
静态成员函数
CCmdTarget的静态成员函数DispatchCmdMsg,用来分发Windows消息。此函数是MFC内部使用的,其原型如下:
static BOOL DispatchCmdMsg(CCmdTarget* pTarget,UINT nID,int nCode,AFX_PMSG pfn,void* pExtra,UINT nSig,AFX_CMDHANDLERINFO* pHandlerInfo)
虚拟函数
CCmdTarget的虚拟函数OnCmdMsg,用来传递和发送消息、更新用户界面对象的状态,其原型如下:
OnCmdMsg(UINT nID,int nCode,void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo)
框架的命令消息传递机制主要是通过该函数来实现的。
命令目标指希望或者可能处理消息的对象;命令目标类指命令目标的类。
CCmdTarget对OnCmdMsg的默认实现:在当前命令目标(this所指)的类和
基类的消息映射
数组里搜索指定命令消息的消息处理函数(标准Windows消息不会送到这里处理)。
这里使用
虚拟函数GetMessageMap得到命令目标类的消息映射入口数组_messageEntries,然后在数组里匹配指定的消息映射条目。匹配标准:命令消息ID相同,控制通知代码相同。因为GetMessageMap是虚拟函数,所以可以确认当前命令目标的确切类。
如果找到了一个匹配的消息映射条目,则使用DispachCmdMsg调用这个处理函数;
如果没有找到,则使用_GetBaseMessageMap得到基类的消息映射
数组,查找,直到找到或搜寻了所有的基类(到CCmdTarget)为止;
如果最后没有找到,则返回FASLE。
每个从CCmdTarget派生的命令目标类都可以覆盖OnCmdMsg,利用它来确定是否可以处理某条命令,如果不能,就通过调用下一命令目标的OnCmdMsg,把该命令送给下一个命令目标处理。通常,
派生类覆盖OnCmdMsg时,要调用
基类的被覆盖的OnCmdMsg。
在MFC框架中,一些MFC命令目标类覆盖了OnCmdMsg,如框架
窗口类覆盖了该函数,实现了MFC的标准命令消息发送路径。
必要的话,应用程序也可以覆盖OnCmdMsg,改变一个或多个类中的发送规定,实现与标准框架发送规定不同的发送路径。例如,在以下情况可以作这样的处理:在要打断发送顺序的类中把命令传给一个非MFC默认对象;在新的非默认对象中或在可能要传出命令的命令目标中。
该类派生于CObject,经封装了MFC的
消息映射机制,希望接收系统事件和窗口消息的类都从它派生,如CDocument和CWnd分支。此外,在系统繁忙,无法响应窗口消息时,鼠标光标应该显示为沙漏等待状态,CCmdTarget类封装了3个成员函数完成该功能。封装COM的IDispatch接口是它的另一项主要功能。IDispatch是COM的标准接口,不含
指针操作的语言(如VB)以及描述性语言(如Web
脚本语言和VBA)都通过该接口操作
COM组件。CCmdTarget类以一种类似消息映射的机制提供IDispatch接口,所以使用MFC可以轻松地编写AUTOMATION客户程序和组件。
CCmdTarget类定义BeginWaitCursor( )、EndWaitCursor( )和RestoreWaitCursor( )3个成员函数处理等待光标。BeginWaitCursor( )将光标设置为沙漏形状,该函数有可能被程序框架调用,通知用户状态忙,例如当加载和存储文档时。EndWaitCursor( )将光标恢复为沙漏之前的形状,一般与BeginWaitCursor( )配合使用。
在实际编程中,在一个比较耗费机时的处理前应该主动调用BeginWaitCursor( )设置光标,在处理结束时要调用EndWaitCursor( )恢复光标。
例如:
void CWaitCursorDoc::LoadFile(char * Filepath)
{
//显示沙漏光标
BeginWaitCursor( );
//耗费机时的处理过程
......
//恢复为沙漏前的光标形状
EndWaitCursor( );
}
如果在BeginWaitCursor( )和EndWaitCursor( )之间的处理中,弹出了
模式对话框,光标会由沙漏变为标准形状(通常是标准箭头)。为处理这种情形,可以在对话框关闭后,调用成员RestoreWaitCursor( )重新将光标设置回沙漏形状,直到处理结束后调用EndWait Cursor( )。例如:
void CWaitCursorDoc::LoadFile(char * Filepath)
{
//显示沙漏光标
BeginWaitCursor( );
//耗费机时的处理过程
if(::FindFirstFile(Filepath,&FindData)==INVALID_HANDLE_VALUE)
{
CFileDlg dlg;
dlg.DoModal( );
//恢复光标的沙漏形状
RestoreWaitCursor( );
}
......
//恢复沙漏前的光标形状
EndWaitCursor( );
}
但如果弹出的是MessageBox( )消息框,就不必调用RestoreWaitCursor( ),光标会自动恢复为沙漏。
在非CCmdTarget派生类中,可以使用CWaitCursor类设置等待光标。该类的
构造函数和
析构函数相当于CCmdTarget::BeginWaitCursor( )和CCmdTarget::EndWaitCursor( ),成员函数Restore( )相当于CCmdTarget:: RestoreWaitCursor( )。