複製鏈接
請複製以下鏈接發送給好友

CCmdTarget

鎖定
類CCmdTarget是MFC類庫中消息映射體系的一個基類,是MFC處理命令消息的基礎、核心。消息映射把命令或消息引導給用户為之編寫的響應函數。
外文名
CCmdTarget
包    括
CView、CWinApp等
設    計
許多成員函數和一些成員數據
基本上
解決消息映射問題的

CCmdTarget簡介

由CCmdTarget [1]  繼承的按鍵框架類包括: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函數”。
所需頭文件:#include <afxwin.h>

CCmdTarget靜態成員函數

CCmdTarget的靜態成員函數DispatchCmdMsg,用來分發Windows消息。此函數是MFC內部使用的,其原型如下:
static BOOL DispatchCmdMsg(CCmdTarget* pTarget,UINT nID,int nCode,AFX_PMSG pfn,void* pExtra,UINT nSig,AFX_CMDHANDLERINFO* pHandlerInfo)

CCmdTarget虛擬函數

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( );
//耗費機時的處理過程
TRACE("正在裝入文件,請等待...\n");
......
//恢復為沙漏前的光標形狀
EndWaitCursor( );
}
如果在BeginWaitCursor( )和EndWaitCursor( )之間的處理中,彈出了模式對話框,光標會由沙漏變為標準形狀(通常是標準箭頭)。為處理這種情形,可以在對話框關閉後,調用成員RestoreWaitCursor( )重新將光標設置回沙漏形狀,直到處理結束後調用EndWait Cursor( )。例如:
void CWaitCursorDoc::LoadFile(char * Filepath)
{
WIN32_FIND_DATA FindData;
//顯示沙漏光標
BeginWaitCursor( );
//耗費機時的處理過程
if(::FindFirstFile(Filepath,&FindData)==INVALID_HANDLE_VALUE)
{
TRACE("打開文件出錯,請重新指定文件\n");
CFileDlg dlg;
dlg.DoModal( );
//恢復光標的沙漏形狀
RestoreWaitCursor( );
}
TRACE("正在裝入文件,請等待...\n");
......
//恢復沙漏前的光標形狀
EndWaitCursor( );
}
但如果彈出的是MessageBox( )消息框,就不必調用RestoreWaitCursor( ),光標會自動恢復為沙漏。
在非CCmdTarget派生類中,可以使用CWaitCursor類設置等待光標。該類的構造函數析構函數相當於CCmdTarget::BeginWaitCursor( )和CCmdTarget::EndWaitCursor( ),成員函數Restore( )相當於CCmdTarget:: RestoreWaitCursor( )。
參考資料