DLL 與 EXE 屬於不同模塊,雖共享進程地址空間,但消息映射表各自獨立。實現跨模塊消息通信需解決:
HWND) 傳遞給 DLL。自定義消息建議從 WM_USER + 100 起步,預留 100 個給系統控件使用,避免衝突:
// 統一放在雙方共用的頭文件或各自 stdafx.h
#define WM_MY_CUSTOM_MSG (WM_USER + 102)
AFX_MSG 區):
afx_msg LRESULT OnMyMsg(WPARAM wParam, LPARAM lParam);
BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
ON_MESSAGE(WM_MY_CUSTOM_MSG, OnMyMsg)
END_MESSAGE_MAP()
LRESULT CTestDlg::OnMyMsg(WPARAM wParam, LPARAM lParam) {
AfxMessageBox(_T("收到 DLL 消息!"));
return 0;
}
extern "C" _declspec(dllexport) void StartSendMessage(HWND hwnd);
void CMessageDLLApp::SendMessage(HWND hwnd) {
::PostMessage(hwnd, WM_MY_CUSTOM_MSG, 0, 1); // 異步發送
}
extern "C" _declspec(dllexport) void StartSendMessage(HWND hwnd) {
theApp.SendMessage(hwnd); // theApp 為 DLL 的 CWinApp 派生對象
}
void CTestDlg::OnBnClickedButton1() {
typedef void (_cdecl *STARTSENDMESSAGE)(HWND);
HMODULE hDll = LoadLibrary(_T("MessageDLL.dll"));
if (!hDll) return;
STARTSENDMESSAGE pfn = (STARTSENDMESSAGE)GetProcAddress(hDll, "StartSendMessage");
if (!pfn) { FreeLibrary(hDll); return; }
HWND hwnd = this->GetSafeHwnd();
pfn(hwnd); // 傳遞自身窗口句柄
// 測試用:也可直接 PostMessage 驗證映射表
// ::PostMessage(hwnd, WM_MY_CUSTOM_MSG, 0, 1);
}
| 特性 | PostMessage | SendMessage |
|---|---|---|
| 調用方式 | 異步,投遞到消息隊列即返回 | 同步,直接調用窗口過程,等待返回 |
| 阻塞風險 | 無 | 若接收方處理慢會阻塞發送線程 |
| 適用場景 | 通知類、高頻事件、跨線程 | 需即時返回值、同步操作 |
HWND (如對話框 GetSafeHwnd()),不可傳 NULL 或錯誤句柄。FreeLibrary 卸載,其導出函數指針失效,切勿在異步回調中使用已卸載 DLL 的代碼/數據。PostMessage 將消息投遞到創建窗口的線程隊列,確保接收方在 UI 線程處理,符合 MFC 單線程 UI 規範。