五步驟快速上手
1. 定義訊息常數
#define WM_MYMESSAGE (WM_USER + 100) // 建議 >= WM_USER+100 避免衝突
2. 類別宣告處理函數
class CMyClass : public CDialog {
// ...
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
3. 訊息映射巨集
BEGIN_MESSAGE_MAP(CMyClass, CDialog)
ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
END_MESSAGE_MAP()
4. 實作處理函數
LRESULT CMyClass::OnMyMessage(WPARAM wParam, LPARAM lParam) {
// wParam/lParam 由發送端自定義內容
return 0;
}
5. 發送訊息
- 同步 (阻塞):
pWnd->SendMessage(WM_MYMESSAGE, w, l);
- 非同步 (投遞佇列):
pWnd->PostMessage(WM_MYMESSAGE, w, l);
- 跨執行緒/進程:
::PostMessage(hWnd, WM_MYMESSAGE, w, l); 或 ::SendMessage
進階應用:多執行緒完成通知主視窗
// 工作執行緒
UINT WorkerThread(LPVOID pParam) {
CWnd* pMain = AfxGetMainWnd(); // 或傳入 HWND
// ... 長時間運算 ...
pMain->PostMessage(WM_THREAD_DONE, (WPARAM)hThread, (LPARAM)result);
return 0;
}
// 主視窗
#define WM_THREAD_DONE (WM_USER + 101)
ON_MESSAGE(WM_THREAD_DONE, OnThreadDone)
LRESULT CMainFrame::OnThreadDone(WPARAM w, LPARAM l) {
HANDLE h = (HANDLE)w; int result = (int)l;
// 更新 UI、釋放資源...
return 0;
}
注意事項
- 訊息 ID 衝突:大型專案建議集中管理
WM_USER+xxx 分配表
SendMessage 跨執行緒會阻塞發送執行緒,UI 執行緒忙碌時可能死鎖,優先用 PostMessage
- 傳遞指標需確保記憶體生命週期 (共享堆疊、
GlobalAlloc、序列化)
- ClassWizard 不支援自訂訊息,需手動編輯 .h/.cpp