類CCmdTarget是MFC類庫中訊息映射體系的一個基類,是MFC處理命令訊息的基礎、核心。訊息映射把命令或訊息引導給用戶為之編寫的回響函式。
基本介紹
- 外文名:CCmdTarget
- 包括:CView、CWinApp等
- 設計:許多成員函式和一些成員數據
- 基本上:解決訊息映射問題的
簡介,靜態成員函式DispatchCmdMsg,虛擬函式OnCmdMsg,
簡介
由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函式”。
所需頭檔案:#include <afxwin.h>
靜態成員函式DispatchCmdMsg
CCmdTarget的靜態成員函式DispatchCmdMsg,用來分發Windows訊息。此函式是MFC內部使用的,其原型如下:
static BOOL DispatchCmdMsg(
CCmdTarget* pTarget,
UINT nID,
int nCode,
AFX_PMSG pfn,
void* pExtra,
UINT nSig,
AFX_CMDHANDLERINFO* pHandlerInfo)
虛擬函式OnCmdMsg
CCmdTarget的虛擬函式OnCmdMsg,用來傳遞和傳送訊息、更新用戶界面對象的狀態,其原型如下:
OnCmdMsg(
UINT nID,
int nCode,
void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
框架的命令訊息傳遞機制主要是通過該函式來實現的。
命令目標指希望或者可能處理訊息的對象;命令目標類指命令目標的類。
這裡使用虛擬函式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(),游標會自動恢復為沙漏。