不需要為每個訊息單獨寫函式,但建議分開。MFC 提供多種機制靈活處理:
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_WM_PAINT()
ON_WM_SIZE()
ON_COMMAND(ID_FILE_PRINT, &CMyView::OnFilePrint)
END_MESSAGE_MAP()
BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
ON_MESSAGE(WM_USER + 1, &CMyWnd::OnCustomMsg)
ON_MESSAGE(WM_USER + 2, &CMyWnd::OnCustomMsg) // 同一函式處理多訊息
END_MESSAGE_MAP()
LRESULT CMyWnd::OnCustomMsg(WPARAM wParam, LPARAM lParam) {
switch (GetCurrentMessage()->message) { // 需自行取得當前訊息 ID
case WM_USER + 1: /*...*/ break;
case WM_USER + 2: /*...*/ break;
}
return 0;
}
GetCurrentMessage() 僅在訊息處理期間有效。控制項通知(WM_COMMAND、WM_NOTIFY)可由父視窗或控制項自身處理:
// 父視窗
ON_NOTIFY_REFLECT(NM_CLICK, &CMyListCtrl::OnClick)
// 控制項類別
ON_NOTIFY_REFLECT_EX(NM_CUSTOMDRAW, &CMyListCtrl::OnCustomDraw)
減少父視窗程式碼,符合封裝原則。
菜單、工具列、快速鍵命令(ID_*)可由:
依序嘗試處理,同一命令只需在最適合的類別實作一次。
| 特性 | 訊息處理函式 | 普通成員函式 |
|---|---|---|
| 簽名限制 | 固定:afx_msg void OnXxx() 或 afx_msg LRESULT OnXxx(WPARAM, LPARAM) | 任意 |
| 呼叫方式 | 透過訊息對應表由架構自動調度 | 直接呼叫 |
| this 指標 | 自動綁定正確物件 | 需物件實例 |
| 可被繼承覆寫 | 是(虛擬函式機制) | 是 |
ON_WM_XXX 巨集,各自獨立函式。ON_MESSAGE 集中 switch 分派。switch 處理所有訊息,破壞可維護性。MFC 訊息對應極具彈性,「每個訊息一函式」是預設最佳實務,但 ON_MESSAGE、反射訊息、命令路由提供合併與分層處理能力。根據訊息性質與數量選擇適當策略,而非強求統一。