CallNextHookEx 是鉤子回調函數中必須呼叫的函數,用於將當前訊息傳遞給鉤子鏈中的下一個鉤子,最終送達目標視窗程序。若省略此呼叫,訊息鏈中斷,後續鉤子與目標視窗將收不到該訊息,導致系統功能異常(如按鍵失效、選單無法彈出)。
function CallNextHookEx(
hhk: HHOOK; // 當前鉤子句柄 (SetWindowsHookEx 返回值)
nCode: Integer; // 鉤子代碼,原樣傳遞
wParam: WPARAM; // 訊息參數,原樣傳遞
lParam: LPARAM // 訊息參數,原樣傳遞
): LRESULT; stdcall; // 返回下一個鉤子/目標視窗的處理結果
HC_ACTION (0) 表示正常處理;負值 (HC_NOREMOVE 等) 必須原樣傳遞,不可修改。lParam 指向的結構體內容。| 常數 | 值 | 含義 |
|---|---|---|
| HC_ACTION | 0 | 正常處理訊息,回調可檢查/修改/攔截 |
| HC_GETNEXT | 1 | Journal 鉤子專用,請求提供下一個回放事件 |
| HC_SKIP | 2 | Journal 鉤子專用,請求跳過當前事件 |
| HC_NOREMOVE | 3 | PeekMessage PM_NOREMOVE 取得訊息,訊息仍留在佇列 |
| HC_SYSMODALON | 4 | 系統進入模態模式 (舊版保留) |
| HC_SYSMODALOFF | 5 | 系統離開模態模式 (舊版保留) |
function MyHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
// 1. 負值代碼直接傳遞,不做任何處理
if nCode < 0 then
begin
Result := CallNextHookEx(hHook, nCode, wParam, lParam);
Exit;
end;
// 2. HC_ACTION: 正常訊息,可在此處理業務邏輯
if nCode = HC_ACTION then
begin
// 例:鍵盤鉤子攔截特定熱鍵
if (wParam = VK_F1) and (GetAsyncKeyState(VK_CONTROL) < 0) then
begin
// 處理 Ctrl+F1 熱鍵
Result := 1; // 非零表示攔截,不再傳遞
Exit;
end;
end;
// 3. 預設情況:傳遞給下一個鉤子
Result := CallNextHookEx(hHook, nCode, wParam, lParam);
end;
CallNextHookEx 的結果。| 錯誤代碼 | 後果 | 修正 |
|---|---|---|
| 忘記呼叫 CallNextHookEx | 鍵盤/滑鼠失效、視窗無法接收訊息 | 在所有分支結構末尾加上 CallNextHookEx |
| 傳遞錯誤的 hhk (如 0 或舊句柄) | 鏈中斷、系統不穩定 | 全域變數保存 SetWindowsHookEx 返回的句柄,回調中引用 |
| 修改 nCode 後傳遞 | 下游鉤子邏輯錯誤 | nCode 必須原樣透傳 |
若需修改訊息(如將 A 鍵映射為 B),可在 WH_KEYBOARD 鉤子中直接修改 lParam 指向的結構體(需確認結構定義),然後正常呼叫 CallNextHookEx。注意:Low-Level 鉤子 (WH_KEYBOARD_LL) 的 lParam 指向 KBDLLHOOKSTRUCT,不可直接修改虛擬鍵碼,需用 SendInput 重新注入。