MFC 消息映射與消息處理

消息映射是將消息處理函數與它要處理的特定消息鏈接起來的一種機制。消息映射是應用 MFC 方法進行 Windows 編程的主要組成部分。

一、消息的類型及其描述

Windows 消息主要有 3 種類型,即標準Windows 消息、控件消息和命令消息。

1.標準Windows 消息

出 WM_COMMAND 以外,所有以“WM_”(Windows Massage)爲前綴的消息都是標準 Windows 消息。標準的 Windows 消息由窗口類或視圖類處理。標準 Windows 消息都有默認的處理函數,這些函數在 CWnd 類中進行了預定義。MFC 類庫以消息名爲基礎形成這些處理函數的名稱,這些函數的名稱都以前綴“On”開始。有的處理函數不帶參數,有的帶幾個參數。這些消息處理函數的說明一般都有“afx_msg”的前綴,用於把處理函數與其他的窗口成員函數區分開來,這些函數都是通過消息映射實現的。例如,消息 WM_CHAR 的處理函數在 CWnd 中聲明爲

  • afx_msg void OnChar();

在afxwin.h中afx_msg的解釋:  
  #ifndef   afx_msg  
  #define   afx_msg                   //   intentional   placeholder  
  #endif  
afx_msg只是定義了這個符號而已。這個對編譯器來說,相當於什麼都沒有,對於程序員來說,我們可以看到這樣的符號。對於類嚮導來說,這個符號纔是有意義的,它是一個消息處理函數的前綴。類嚮導生成的消息函數,分發函數,事件響應函數都以這個爲前綴,如果去掉了,嚮導將不能識別。

標準的 Windows 消息又分爲 3 類:鍵盤消息、鼠標消息和窗口消息。

(1)鍵盤消息

鍵盤消息與鍵盤某個鍵的動作相關聯。常見的鍵盤消息有以下幾種。

  • WM_KEYDOWN、WM_KEYUP:按下、釋放非系統鍵產生的消息。
  • WM_CHAR:輸入非系統字符時產生的消息。

所有鍵盤消息處理函數的原型都很相似。以 WM_CHAR 消息處理函數 OnChar()爲例來說明。此函數的原型爲

  • afx_msg void OnChar(UINT nChar,  UINT nRepCnt,  UINT nFlags);

其中,參數 nChar是所按鍵的字符代碼值;nRepCnt 表示用戶重複擊鍵的次數;nFlags表示掃描碼、先前鍵狀態和鍵轉換狀態等,其具體含義如表所示

nFlags取值 含義
0~7 表示掃描碼
8

若同時按下擴展鍵,則置位;否則清位

9,10 不使用
11,12 有 Windows 內部使用
13 若同時按下 Alt 鍵,則置位;否則清位
14 指明先前鍵狀態。如果消息發出前鍵是按下的,則置位;否則清位
15 指明鍵轉換狀態。如果按鍵已鬆開,則置位;否則清位

(2)鼠標消息

鼠標消息設計鼠標的單擊、雙擊、拖動。常用的鼠標消息有以下幾種:

  • WM_MOUSEMOVE:鼠標移動時產生的消息。
  • WM_RBUTTONDOWM:鼠標右鍵按下時產生的消息。
  • WM_LBUTTONDOWN:鼠標左鍵按下時產生的消息。
  • WM_LBUTTONDBLCLICK:鼠標雙擊時產生的消息。

所有鼠標操作的處理函數都有很相似的原型,他們都有兩個參數。以處理鼠標左鍵按下消息的函數 OnLButtonDown()爲例。此函數的原型爲:

  • afx_msg void OnLButtonDown(UINT nFlags,  CPoint point);

其中,參數 point 是鼠標事件發生時鼠標所在的位置。它是相對於窗口左上角的水平 X 座標和垂直 Y 座標而言的。參數nFlags 指明鼠標按鍵的狀態以及鼠標事件發生時鍵盤上某些鍵的狀態,每一狀態都可以用nFlags 的一位表示,具體函數見表

nFlags取值 含義 nFlags取值 含義
 MK_CONTROL Ctrl 鍵按下 MK_RBUTTON 右鍵按下
MK_LBUTTON 左鍵按下 MK_SHIFT shift 鍵按下
MK_MBUTTON 中間鍵按下    

(3)窗口消息

窗口消息一般與創建窗口、繪製窗口、移動窗口和銷燬窗口等動作有關。在 MFC 應用程序彙總,窗口消息是由視圖類、窗口類及它們的派生類處理的。常見的窗口消息如下:

WM_PAINT:當客戶區產生移動或者顯示事件、當用戶窗口產生改變大小事件、當產生下拉菜單關閉並需要恢復被覆蓋部分事件、當產生 Windows 清除對話框或者消息框並需要恢復被覆蓋部分事件時,會產生 WM_PAINT 消息。它的消息處理函數原型爲:

  • afx_msg void OnPaint();

WM_TIMER:每當定時器被觸發時,系統就發送 WM_TIMER 消息。它的消息處理函數原型爲

  • afx_msg void OnTimer(UINT nIDEvent);

其中,參數nIDEvent是計時器的標識符。

這裏還有博主寫的對話框的常用回調函數(窗口創建時的消息和窗口銷燬時的消息) https://blog.csdn.net/qq_41291253/article/details/89203975

 2.控件消息

控件消息是指控件或其他子窗口向父窗口發送 WM_COMMAND 消息。發送控件消息的控件使用唯一的 ID 來識別,使用控件類來操控。從控件傳給系統的消息,它的前綴的最後一個字符爲 N;由系統發送給控件的消息,其前綴的最後一個字符爲M

例如,當用戶對編輯框中的文本進行修改時,編輯框將發送給父窗口一條包含控件通知碼 EN_CHANGE 的 WM_COMMAND 消息。與其他標準 Windows 消息一樣,控件消息也應該在視圖類、窗口類中進行處理。但是,如果用戶單擊按鈕控件時,發出的控件通知消息 BN_CLICKED 將作爲命令消息來處理。

3.命令消息

命令消息是由菜單項、工具欄按鈕、快捷鍵等用戶界面對象發出的 WM_COMMAND 消息。命令消息與其他消息不同,他可被更廣泛的對象如文檔、文檔模板、應用程序對象、窗口和視圖處理。

二、MFC 消息映射機制

MFC 採用消息映射來處理消息。這種消息映射機制包括一組消息映射宏,用於把一個 Windows 消息其消息處理函數聯繫起來。MFC 應用程序框架提供了消息映射功能,所有從 CCmdTarget 類派生出來的類都能夠擁有自己的消息映射。

與 MFC 消息映射機制有關的宏有以下 3 個:DECLARE_MESSAGE_MAP()宏、BEGIN_MESSAGE_MAP(MyClass, MybaseClass)宏和 END_MESSAGE_MAP()宏。

爲了使用消息映射宏,首先在類定義的結尾用 DECLEAR_MESSAGE_MAP()宏來聲明使用消息映射,該宏表示在爲各個處理函數所寫的類聲明之後存在消息映射條目,這些函數是該類的成員函數。然後在類的實現源文件中用BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()宏來定義消息映射。MFC 應用程序 MESSAGE_MAP 消息映射的形式如下。

BEGIN_MESSAGE_MAP(MyClass, MybaseClass)
    //{{AFX_MSG_MAP(MyClass)         //類嚮導維護消息映射宏的標記
    ON_...                           //MFC 預定義消息映射宏
    ON_MESSAGE(message, memberFun)   //用戶自定義消息映射宏
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

其中,MyClass 是擁有消息映射的派生類名,MyBaseClass 是其基類名。對於不同類型的消息,消息映射宏的格式及參數是不同的,見下表。

消息映射宏格式
消息類型 宏格式 參數
標準 Windows 消息 ON_WM_XXX
命令消息 ON_COMMAND 命令消息 ID,消息處理函數名
用戶界面更新命令消息 ON_UPDATE_COMMAND_UI 命令消息 ID,消息處理函數名
空間通知消息 ON_CONTROL 控件消息 ID,消息處理函數名
用戶自定義消息 ON_MESSAGE 自定義消息 ID,消息處理函數名
已註冊用戶自定義消息 ON_REGISTERED_MESSAGE 自定義消息 ID,消息處理函數名
命令 ID 範圍 ON_COMMAND_RANGE 連續範圍內命令 ID 的開始和結束
更新命令 ID 範圍 ON_UPDATE_COMMAND_UI_RANGE 連續範圍內命令 ID 的開始和結束
空間的 ID 範圍 ON_CONTROL_RANGE 控件通知碼和連續範圍內的命令 ID 的開始和結束

具體demo 請見博主另一篇文章:MFC 消息映射機制 https://blog.csdn.net/qq_41291253/article/details/103321786

三、自定義消息處理

自定義消息步驟如下:

1.定義消息 ID 值

2.聲明自定義消息處理函數

3.在消息映射表中添加自定義消息映射宏

4.定義自定義消息的實現代碼

5.在需要運行自定義消息的地方發送自定義消息。

具體請看博主的這篇文章  用戶自定義消息:https://blog.csdn.net/qq_41291253/article/details/103321802

發佈了54 篇原創文章 · 獲贊 34 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章