消息循環是線程級的消息分發機制(GetMessage → TranslateMessage → DispatchMessage),唯一;
消息映射是窗口類級的消息處理函數查找表(巨型 switch-case 的宏實現),每個窗口類各有一套。
兩者層級不同、職責不同、不衝突、不可替代。
CWinApp::Run() 中,主線程唯一運行。DispatchMessage 內部調用窗口進程 WindowProc)。AFX_MSGMAP_ENTRY,包含 消息ID、處理函數指針、參數類型。WindowProc → AfxCallWndProc → 遍歷當前類及基類 messageMap,匹配消息 ID,調用對應 Handler。switch,支持繼承複用(派生類自動繼承基類映射)。| 維度 | 消息循環 | 消息映射 |
|---|---|---|
| 層級 | 線程/進程級 | 窗口類級 |
| 數量 | 主線程唯一 | 每個 CWnd 派生類一套 |
| 核心代碼 | CWinApp::Run() | BEGIN_MESSAGE_MAP / ON_COMMAND / END_MESSAGE_MAP |
| 可否自定義 | 可重寫 Run() 或掛鉤 PreTranslateMessage | 自由添加 ON_XXX 宏 |
| 與 WndProc 關系 | 調用 DispatchMessage 間接觸發 | 被 WindowProc 通過映射表調用 |
「消息循環只有一個處理函數,消息映射有很多函數」
❌ 錯誤理解。消息循環無處理函數,只分發;消息映射每個消息對應一個處理函數,但屬於同一窗口類,而非全局。
CWinApp::Run 跑循環,CWnd::WindowProc 自動查映射表。PreTranslateMessage 或自定義循環。while(GetMessage...) 循環,自行 DispatchMessage,此時無映射表,需在 WndProc 手寫 switch。參考經典博客:《MFC 消息循環與消息映射機制深度解析》,含宏展開源碼級分析。