MFC消息彙總

1、命令消息(WM_COMMAND)

 

    所有派生自 CCmdTarget 的類都有資格接受WM_COMMAND。

 

2、Window消息(WM_xxx)

 

   所有派生自 CWnd 的類都有資格接受 WM_xxx。

 

3、控件消息(WM_NOTIFY)

    控件向其父窗口通知消息。

 

消息處理

1、WM_xxx 消息處理

     窗口類(自身)處理→基類處理→CWnd∷DefWindowProc()處理; 其所對應的宏一般爲在消息 WM_ 前面加上 ON_。

2、命令消息處理

      命令消息來自命令用戶接口對象(菜單、加速鍵或工具欄按鈕)發出的WM_COMMAND消息;

    ㈠、WM_COMMAND消息 其所包含的類型和對應的宏如下:

          ①、ON_COMMAND(ID,pfn) 標準的命令消息;

          ②、ON_COMMAND_EX(ID,pfn) 多個對象對同一個命令 ID 的處理; 其函數的原型如下: afx_msg BOOL pfn(UINT nID) 說明: 當返回 TRUE 時表示已經處理,不用在消息處理鏈中繼續處理該命令;爲 FALSE 時表示繼續在消息處理鏈中處理該命令。

          注意:

            其一:在多對象處理中一定要使用該宏;

            其二:pfn(UINT nID)(消息處理函數)返回值將其類型void改成BOOL,而且必須爲FALSE;

            其三:多個對象的處理是由高層向低層的過程:即視圖類→主框架窗口類→應用程序類;

           ③、ON_COMMAND_RANGE(nID,nLastID,pfn) 多個命令 ID 提供相同的處理;

           注意:

            其一:確保nID、nLastID的值在 Resource.h 中是連續的。

            其二:一般在函數 pfn(UINT nID) 中加入參數,用來確定那一個按鈕點擊。

     ㈡、CN_UPDATE_COMMAND_UI消息 當菜單項、工具欄按鈕等[命令用戶接口對象]要更新其狀態時所對應的消息,它所包含的類型和對應的宏如下:

           ①、ON_UPDATE_COMMAND_UI(ID,pfn) 其中函數的原型如下: afx_msg void pfn(CCmdUI* pCmdUI)

           ②、ON_UPDATE_COMMAND_UI_RANGE(nID,nLastID,pfn) 該函數可以處理一組[命令用戶接口對象]的外觀; 其中函數的原型如下: afx_msg void pfn(CCmdUI* pCmdUI) 重要: CCmdUI 中的 m_nID 成員表示不同的 ID,因此可以利用它來進行區別處理。

 

3、控件的通知消息

       從控件和子窗口發送到父窗口的WM_COMMAND通知消息(即在發送命令消息中加入控件的通知碼)。 注意:在 Window9x 新控件中不再傳送WM_COMMAND通知消息,而是發送 WM_NOTIFY 消息,但爲了兼容,舊有的控件還是傳送WM_COMMAND消息。 例如: CEdit控件向父窗口發送 EN_CHANGE 通知代碼的WM_COMMAND消息。 注意:框架像傳送其它 WM_ 消息一樣傳送通知消息,但有一個例外,即由 [按鈕] 控件發送的 BN_CLICKED 通知消息,被作爲命令消息特別處理。

        ㈠、WM_COMMAND 其所對應的宏如下:

              ①、ON_CONTROL(通知碼, nID,fn)

              ②、ON_CONTROL_RANGE(通知碼, nFirstID,nEndID,fn) 注意: 這兩個宏的應用和 ON_COMMAND、ON_COMMAND_RANGE相同,所不同的是在宏前面加入[通知碼]。 注意:可以根據不同的控件的[通知碼]派生出特定的宏,其所派生的宏一般爲在 [通知碼] 前面加上 ON_。

         ㈡、WM_NOTIFY 其所對應的宏如下:

              ①、ON_NOTIFY(通知碼, nID,fn) 其中函數的原型如下: afx_msg void fn(NMHDR* pNotifyStruct,LRESULT* result) 其中結構: typedef struct tagNMHDR { HWND hwndFrom; //發送通知消息的控件的句柄; UINT idFrom; //發送通知消息的控件的 ID; UINT code; //通知碼; } NMHDR;

             ②、ON_NOTIFY_EX(通知碼, nID,fn) 表示一個消息在多個對象的成員函數中進行處理。 其中函數的原型如下: afx_msg BOOL fn(UINT nID,NMHDR* pNotifyStruct,LRESULT* result) 說明: 它必須返回 BOOL 類型的數值,其意義和 ON_COMMAND_EX 相同。

              ③、ON_NOTIFY_RANGE(通知碼, nFirstID,nEnd,fn) 表示多個控件的通知消息在同一個函數中進行處理。 其中函數的原型如下: afx_msg void fn(UINT nID,NMHDR* pNotifyStruct,LRESULT* result) 說明: 其意義和ON_COMMAND_RANGE相同。

 

 4、反射消息處理

        父窗口在處理控件窗口的通知消息WM_CTLCOLOR、WM_COMMAND、WM_NOTIFY時,會把該消息轉化爲反射消息,並轉交給控件子窗口處理,只有在控件子窗體不處理該消息時,父窗口才有機會處理。

        注意:在類的屬性對話框中的消息頁面可查反射消息(前面有"="標誌)

        ①、WM_CTLCOLOR_REFLECT反射消息 其所對應的宏如下: ON_WM_CTLCOLOR_REFLECT() 反射消息函數的原型: HBRUSH class_name∷CtlColor(CDC* pDC,UINT nCtlColor) { return NULL; } 該函數用來重置控件的顔色;注意:必須 return CBrush纔有效。

 

5、自定義的窗口消息

        自定義窗口消息的消息標誌都大於WM_USER(至少是WM_USER+100,因爲許多控件都使用這一範圍的WM_USER消息) 使用自定義的消息分爲二步:

         ①、在 Resource.h 中定義消息標記 #define WM_MYMSG (WM_USER+1000)

         ②、在消息映射表中加入消息映射宏 BEGIN_MESSAGE_MAP() ON_MESSAGE(WM_MYMSG,fn) END_MESSAGE_MAP() 說明: 其對應的宏爲 ON_MESSAGE(),其成員函數的原型爲: afx_msg LRESULT fn(WPARAM,LPARAM)

 

6、登記消息

         ①、在系統中註冊並獲取一個登記消息的消息標記 UINT RegisterWindowMessage(LPCTSTR) 說明: 通過 API 函數來註冊消息標記,其中 LPCTSTR 爲用戶的任意字符串。

        例如: UINT WM_MYMSG=RegisterWindowMessage("MYMSG"); 其中 WM_MYMSG 是自定義無符號整型的消息標記。

       

        ②、在消息映射表中加入消息映射宏 BEGIN_MESSAGE_MAP() ON_REGISTERED_MESSAGE(WM_MYMSG,fn) END_MESSAGE_MAP() 說明: 其對應的宏爲 ON_REGISTERED_MESSAGE(),其成員函數的原型爲: afx_msg LRESULT fn(WPARAM,LPARAM) 注意:登記消息可以實現跨進程的數據通訊。

 

7、線程消息

       只有繼承自CWinThread類才能允許處理線程消息。

        ①、定義線程的消息標記 有兩種方法:

               (1)、使用自定義的消息標記,即:WM_USER;

               (2)、使用登記的消息標記,即:RegisterWindowMessage;

        ②、在CWinThread繼承類的消息映射表中添加宏 ON_THREAD_MESSAGE(消息標記,fn) //自定義的消息; ON_REGISTERED_THREAD_MESSAGE(消息標記,fn) //登記的 //消息

        ③、其函數的原型如下: afx_msg void fn(WPARAM wPARAM,LPARAM lParam)

        ④、引發線程消息 線程消息的引發必須調用 CWinThread 類的PostThreadMessage將消息投遞到線程消息隊列中。

         注意:可以通過 AfxGetApp() 函數獲取一個全局的應用對象。 PostThreadMessage(UINT,WPARAM,LPARAM)

 

8、WM_COPYDATA

        操作系統維護一塊內存來管理 WM_COPYDATA 消息,該消息主要用於跨進程傳遞數據,傳遞的數據量達到 232。

        ①、定義一個 COPYDATASTRUCT 數據結構 typedef struct tagCOPYDATASTRUCT { DWORD dwData; //自定義的特殊數據; DWORD cbData; //以字節爲單位的 lpData 的大小; PVOID lpData; //傳送的數據內存塊的指針; } COPYDATASTRUCT;          

        ②、其所對應的宏 ON_WM_COPYDATA()

        ③、其所對應的函數的原型 afx_msg BOOL OnCopyData(CWnd*,COPYDATASTRUCT*) 說明: CWnd*:發送該消息的窗口的指針;

 

9、投遞和發送消息

        通過向一個窗體投遞或發送消息,可以間接地驅動窗體的消息過程。 投遞(PostMessage):將消息放到線程的消息隊列中,然後不等線程處理該消息就直接返回到調用方。 發送(SendMessage):當一個線程向目標線程發送消息時,該線程要一直等待,直到目標線程處理了該消息爲止。

        ①、投遞消息 BOOL CWnd∷PostMessage(UINT,WPARAM=0,LPARAM=0) 說明: CWnd:目標窗口; 該函數將一條消息放入到應用程序的消息隊列,然後不等窗口處理就直接返回。

        ②、發送消息 LRESULT CWnd∷SendMessage(UINT,WPARAM=0,LPARAM=0) 說明: CWnd:目標窗口; 該函數將一條消息放入到應用程序的消息隊列,等待窗口處理後才返回。 爲了避免線程陷入永久等待狀態,可以用SendMessageTimeout代替SendMessage: LRESULT SendMessageTimeout(HWND,UINT,WPARAM,LPARAM,UINT,UINT,PDWORD_PTR) 說明: HWND:窗口句柄; UINT:消息發送的選項,爲SMTO_BLOCK時,可以防止線程無 限等待,即根據一定的超時值返回。 UINT:超時,以毫秒爲單位; PDWORD_PTR:返回值; 注意:CWnd沒有對該函數的包裝。

        ③、投遞和發送消息 BOOL CWnd∷SendNotifyMessage(UINT,WPARAM,LPARAM) 說明: CWnd:目標窗口; 該消息具有SendMessage和PostMessage兩種功能: 當目標窗口和發送窗口爲同一個線程時,則相當於SendMessage的功能;否則當不爲同一個線程時,則爲PostMessage的功能。

 

6-1、投遞和發送 WM_XXX 消息

        在發送標準的 WINDOW 消息時,只要將該消息的 ID、wParam、lParam參數放在 SendMessage()和PostMessage()函數的相應位置即可。

 

 6-2、投遞和發送命令消息和控件的通知消息

         在投遞和發送命令消息時,消息的 ID爲 WM_COMMADN,而對於不同的菜單項、加速鍵、控件則wParam、lParam的取值不同。 wParam分成低、高兩部分,低部分爲菜單項、加速鍵、控件的ID。高部分則: 菜單項:0;加速鍵:1;控件:通知碼 lParam:當控件時是控件的句柄,否則爲 NULL。 對於wParam參數可以採用自定義宏: WPARAM MAKEWPARAM(WORD wLow,WORD wHigh)

 

6-3、投遞和發送自定義的窗口消息

        在投遞和發送自定義的窗口消息時,參數 wParam、lParam 沒有特別的涵義,只和普通函數的形參一樣進行數據的傳遞。 注意: PostMessage 和 SendMessage 是不同的,前者投遞後就返回,而後者必須等到消息處理後再返回;所以在參數是 [局部] 或 [臨時]時,使用PostMessage函數會引發錯誤(除非參數使用 指針,則可避免錯誤),而必須使用SendMessage函數。

 

 6-4、投遞和發送註冊的窗口消息

       和 6-3 基本一樣,但它要特別注意的問題是:在跨進程的處理消息時,如果將消息PostMessage、SendMessage到某個進程 A,則必須在進程 B 中獲取進程 A 的窗口類名,並通過窗口類名獲取窗口的指針,最後再根據指針調用 PostMessage、SendMessage 函數。 注意:在獲取窗口的指針時,可以根據窗口類名或窗口的標題。

 

6-5、投遞和發送WM_COPYDATA消息

 

        SendMessage(消息標記,WPARAM,LPARAM) 其中: 消息標記:WM_COPYDATA; WPARAM:發送該消息的窗口句柄; LPARAM:COPYDATASTRUCT結構的指針,先通過(LPVOID)進行轉換,再通過(LPARAM)進行轉換,如下形式: (LPARAM)(LPVOID)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章