首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

MFC 消息映射機制深度解析(上):從 Windows 消息架構到 MFC 封裝實現

     編輯:關於VC++

前言:為何要理解消息映射?

在 MFC 開發中,消息映射是連接 Windows 作業系統與應用程式邏輯的核心橋樑。雖然 ClassWizard 等工具讓我們能輕鬆添加訊息處理函式,但深入理解其底層實作原理,不僅有助於排查疑難雜症,更能讓我們在需要時靈活擴展框架功能。本文將從 Windows 訊息機制基礎出發,層層剖析 MFC 如何封裝並實現高效的訊息映射與分發。

一、Windows 訊息機制回顧

1.1 訊息的分類與流向

Windows 程式的輸入皆以「訊息」形式傳遞。依傳遞路徑可分為:

  • 佇列訊息:如滑鼠、鍵盤事件(WM_MOUSEMOVE、WM_KEYDOWN 等)、WM_PAINT、WM_TIMER、WM_QUIT。它們先進入系統訊息佇列,再由 Windows 分派至建立視窗的執行緒佇列,最後經由 GetMessage/DispatchMessage 迴圈送達視窗程序。
  • 非佇列訊息:直接發送給目標視窗程序,不經佇列。絕大多數系統訊息屬此類。

依來源分類則有系統訊息(0 ~ WM_USER-1、0x8000 ~ 0xBFFF)與應用程式自訂訊息(WM_USER ~ 0x7FFF、0xC000 ~ 0xFFFF)。後者若需跨程式通訊,應用 RegisterWindowMessage 保證 ID 唯一性。

1.2 訊息結構與視窗程序

每筆訊息以 MSG 結構描述:視窗句柄、訊息 ID、兩個 32 位參數、時間戳記、滑鼠座標。視窗程序原型為:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

應用程式在視窗程式內以 switch-case 判別訊息並處理。主迴圈典型寫法:

while (GetMessage(&msg, NULL, 0, 0)) {
    if (!TranslateAccelerator(...) && !IsDialogMessage(...)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

二、MFC 如何簡化訊息處理

MFC 最大的貢獻在於:所有 MFC 視窗共用同一視窗程序(AfxWndProc),開發者無需自行編寫龐大的 switch-case,而是透過「訊息映射」機制,將訊息 ID 與類別成員函式建立對應關係。

2.1 MFC 處理的三大類訊息

  1. Windows 訊息(WM_ 開頭,WM_COMMAND 除外):直接由視窗物件(CWnd 派生類)處理。
  2. 控制項通知訊息:子視窗發送 WM_COMMAND 給父視窗,同樣由視窗物件處理。Win32 另引入 WM_NOTIFY 支援更複雜通知。
  3. 命令訊息:源自選單、工具列、快速鍵的 WM_COMMAND。MFC 採用「命令路由」機制,沿文件、視圖、框架視窗、應用程式等 CCmdTarget 派生物件尋找處理器。

2.2 ClassWizard 產生的程式碼結構

在類別宣告(.h)中:

//{{AFX_MSG(CMyClass)
afx_msg void OnMyMessage();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()

在類別實作(.cpp)中:

BEGIN_MESSAGE_MAP(CMyClass, CBaseClass)
    ON_MESSAGE(WM_MYMSG, OnMyMessage)
END_MESSAGE_MAP()

void CMyClass::OnMyMessage() { ... }

DECLARE_MESSAGE_MAP 與 IMPLEMENT_MESSAGE_MAP(展開為 BEGIN_MESSAGE_MAP/END_MESSAGE_MAP)是核心巨集,下一篇將深入剖析其內部實作與訊息分發流程。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved