Windows 提供鉤子鏈機制:系統產生訊息 → 依序傳遞給鉤子鏈中的每個回調函數 → 回調可監控/修改/攔截/傳遞 → 最後達到目標視窗程序。鉤子類似「可擴展的中斷向量表」。
| 常數 | 用途 | 典型場景 |
|---|---|---|
| WH_KEYBOARD | 鍵盤訊息 (WM_KEYDOWN/UP/CHAR) | 熱鍵、鍵盤記錄、輸入法 |
| WH_MOUSE | 滑鼠訊息 | 滑鼠手勢、記錄回放 |
| WH_GETMESSAGE | GetMessage/PeekMessage 返回前 | 訊息日誌、防掛機制 |
| WH_CALLWNDPROC | 呼叫視窗程序前 | 參數檢查、API 攔截 |
| WH_CBT | 視窗建立/銷毀/啟動/移動/大小變更 | 視窗管理、自動排版 |
| WH_JOURNALRECORD | 記錄輸入流 (鍵盤/滑鼠) | 巨集錄製、自動化測試 |
| WH_JOURNALPLAYBACK | 重放記錄的輸入流 | 巨集回放、演示腳本 |
| WH_DEBUG | 除錯器專用 | IDE 除錯支援 |
| WH_SHELL | Shell 事件 (視窗建立/銷毀/啟動/閃爍) | 任務列、桌面管理 |
| WH_MSGFILTER | 對話框/選單/捲軸訊息循環 | 模態循環攔截 |
| WH_SYSMSGFILTER | 系統級訊息過濾 | 系統級熱鍵 |
WH_KEYBOARD) 詳細實作LRESULT CALLBACK KeyboardProc(
int nCode, // HC_ACTION(0) 表示處理訊息,負值傳遞下一個
WPARAM wParam, // 虛擬鍵碼
LPARAM lParam // 掃描碼、擴展鍵、前次狀態、轉換狀態等
);
SetWindowsHookEx// 全域鉤子 (影響所有執行緒) - 必須在 DLL 中
HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hDllInstance, 0);
// 執行緒專用鉤子 - 可在 EXE 中
HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, dwThreadId);
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// 1. 負碼直接傳遞
if (nCode < 0)
return CallNextHookEx(hHook, nCode, wParam, lParam);
// 2. HC_ACTION (0) 時處理
if (nCode == HC_ACTION) {
bool bKeyDown = !(lParam & 0x80000000); // 位 31: 0=按下, 1=釋放
int vk = (int)wParam;
// 業務邏輯:例如攔截 Alt+F4
if (vk == VK_F4 && (GetAsyncKeyState(VK_MENU) & 0x8000)) {
// 吞噬訊息:不呼叫 CallNextHookEx,直接返回非零
return 1;
}
// 記錄按鍵...
}
// 3. 傳遞給下一個鉤子
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
| 維度 | 全域鉤子 | 執行緒鉤子 |
|---|---|---|
| DLL 必須 | 是 | 否 (可在 EXE) |
| 影響範圍 | 同桌面所有執行緒 | 指定執行緒 |
| 效能影響 | 較大 (每個訊息皆經過) | 極小 |
| 適用場景 | 系統級熱鍵、鍵盤記錄器 | 應用內部快捷鍵、輸入法 |
__declspec(dllexport) 或 .def 導出。CALLBACK = __stdcall,參數順序嚴格遵守。WH_JOURNALRECORD 更會同步阻塞輸入。UnhookWindowsHookEx(hHook) 必須在 DLL 卸載前呼叫,否則系統殘留鉤子導致崩潰。// 模式 1:全域熱鍵 (DLL + 共享記憶體通訊 EXE)
共享記憶體結構 { HWND hTargetWnd; UINT uMsg; WPARAM wParam; LPARAM lParam; }
// 鉤子偵測到熱鍵 → PostMessage 給目標視窗
// 模式 2:輸入法/軟鍵盤 (執行緒鉤子 + 修改 lParam)
修改 lParam 的虛擬鍵碼/掃描碼 → 實現鍵位重映射
// 模式 3:防掛機制 (WH_GETMESSAGE)
檢查訊息循環是否長時間無回應 → 重啟/報警

鉤子是 Windows 可擴展性的核心支柱,善用它能實現框架層面無法觸及的深層系統互動。