首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

WinAPI:CallNextHookEx 傳遞鉤子鏈關鍵函數

     編輯:Delphi

CallNextHookEx 核心作用

CallNextHookEx 是鉤子回調函數中必須呼叫的函數,用於將當前訊息傳遞給鉤子鏈中的下一個鉤子,最終送達目標視窗程序。若省略此呼叫,訊息鏈中斷,後續鉤子與目標視窗將收不到該訊息,導致系統功能異常(如按鍵失效、選單無法彈出)。

函數原型

function CallNextHookEx(
  hhk: HHOOK;       // 當前鉤子句柄 (SetWindowsHookEx 返回值)
  nCode: Integer;   // 鉤子代碼,原樣傳遞
  wParam: WPARAM;   // 訊息參數,原樣傳遞
  lParam: LPARAM    // 訊息參數,原樣傳遞
): LRESULT; stdcall; // 返回下一個鉤子/目標視窗的處理結果

參數詳解

  • hhk:雖然文檔說可傳 0,但強烈建議傳入當前鉤子句柄,確保系統正確定位鏈中位置,特別在多鉤子共存時。
  • nCode:HC_ACTION (0) 表示正常處理;負值 (HC_NOREMOVE 等) 必須原樣傳遞,不可修改。
  • wParam / lParam:訊息具體內容,通常原樣透傳;若需修改訊息(如鍵盤重映射),可在傳遞前修改 lParam 指向的結構體內容。

nCode 常見值對照表

常數值含義
HC_ACTION0正常處理訊息,回調可檢查/修改/攔截
HC_GETNEXT1Journal 鉤子專用,請求提供下一個回放事件
HC_SKIP2Journal 鉤子專用,請求跳過當前事件
HC_NOREMOVE3PeekMessage PM_NOREMOVE 取得訊息,訊息仍留在佇列
HC_SYSMODALON4系統進入模態模式 (舊版保留)
HC_SYSMODALOFF5系統離開模態模式 (舊版保留)

典型回調模板

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;

關鍵規則與最佳實踐

  1. 永遠呼叫 CallNextHookEx,除非你明確要攔截並吞噬該訊息(返回非零值)。
  2. 保持鉤子鏈完整:一個壞掉的鉤子(不呼叫 CallNextHookEx)會影響所有後續鉤子與目標視窗。
  3. 返回值語義:
    • 大多數鉤子:返回 CallNextHookEx 的結果。
    • WH_KEYBOARD/MOUSE:返回非零表示攔截(丟棄訊息),零表示繼續傳遞。
    • WH_GETMESSAGE/CALLWNDPROC:返回值通常被忽略,仍會傳遞。
  4. 效能:CallNextHookEx 開銷極小,但回調邏輯必須極簡,避免阻塞訊息泵。

常見錯誤案例

錯誤代碼後果修正
忘記呼叫 CallNextHookEx鍵盤/滑鼠失效、視窗無法接收訊息在所有分支結構末尾加上 CallNextHookEx
傳遞錯誤的 hhk (如 0 或舊句柄)鏈中斷、系統不穩定全域變數保存 SetWindowsHookEx 返回的句柄,回調中引用
修改 nCode 後傳遞下游鉤子邏輯錯誤nCode 必須原樣透傳

進階:修改訊息內容

若需修改訊息(如將 A 鍵映射為 B),可在 WH_KEYBOARD 鉤子中直接修改 lParam 指向的結構體(需確認結構定義),然後正常呼叫 CallNextHookEx。注意:Low-Level 鉤子 (WH_KEYBOARD_LL) 的 lParam 指向 KBDLLHOOKSTRUCT,不可直接修改虛擬鍵碼,需用 SendInput 重新注入。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved