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

Windows 鍵盤鉤子原理與應用:SetWindowsHookEx 實現全域/執行緒級監控

     編輯:VC 教學

鉤子機制核心概念

Windows 提供鉤子鏈機制:系統產生訊息 → 依序傳遞給鉤子鏈中的每個回調函數 → 回調可監控/修改/攔截/傳遞 → 最後達到目標視窗程序。鉤子類似「可擴展的中斷向量表」。

11 種標準鉤子類型

常數用途典型場景
WH_KEYBOARD鍵盤訊息 (WM_KEYDOWN/UP/CHAR)熱鍵、鍵盤記錄、輸入法
WH_MOUSE滑鼠訊息滑鼠手勢、記錄回放
WH_GETMESSAGEGetMessage/PeekMessage 返回前訊息日誌、防掛機制
WH_CALLWNDPROC呼叫視窗程序前參數檢查、API 攔截
WH_CBT視窗建立/銷毀/啟動/移動/大小變更視窗管理、自動排版
WH_JOURNALRECORD記錄輸入流 (鍵盤/滑鼠)巨集錄製、自動化測試
WH_JOURNALPLAYBACK重放記錄的輸入流巨集回放、演示腳本
WH_DEBUG除錯器專用IDE 除錯支援
WH_SHELLShell 事件 (視窗建立/銷毀/啟動/閃爍)任務列、桌面管理
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);
}

全域 vs 執行緒鉤子選型

維度全域鉤子執行緒鉤子
DLL 必須是否 (可在 EXE)
影響範圍同桌面所有執行緒指定執行緒
效能影響較大 (每個訊息皆經過)極小
適用場景系統級熱鍵、鍵盤記錄器應用內部快捷鍵、輸入法

關鍵注意事項

  • DLL 導出:回調函數必須 __declspec(dllexport) 或 .def 導出。
  • 協調呼叫慣例:CALLBACK = __stdcall,參數順序嚴格遵守。
  • 效能:鉤子鏈越長、回調越複雜,系統輸入延遲越大。WH_JOURNALRECORD 更會同步阻塞輸入。
  • 卸載:UnhookWindowsHookEx(hHook) 必須在 DLL 卸載前呼叫,否則系統殘留鉤子導致崩潰。
  • 64 位相容:32 位鉤子無法攔截 64 位進程,需分別編譯 32/64 位 DLL。
  • UAC/完整性等級:低完整性進程無法鉤子高完整性進程 (如系統管理員視窗)。

實戰應用模式

// 模式 1:全域熱鍵 (DLL + 共享記憶體通訊 EXE)
共享記憶體結構 { HWND hTargetWnd; UINT uMsg; WPARAM wParam; LPARAM lParam; }
// 鉤子偵測到熱鍵 → PostMessage 給目標視窗

// 模式 2:輸入法/軟鍵盤 (執行緒鉤子 + 修改 lParam)
修改 lParam 的虛擬鍵碼/掃描碼 → 實現鍵位重映射

// 模式 3:防掛機制 (WH_GETMESSAGE)
檢查訊息循環是否長時間無回應 → 重啟/報警

Windows 鉤子鏈架構圖

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

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