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

鍵盤鉤子開發按鍵發音程式:從理論到完整實現

     編輯:關於VC++

需求緣起

為協助長輩練習盲打,開發一款按鍵即發音的小工具:系統全局攔截鍵盤事件,播放對應音檔。

鉤子原理與 API

SetWindowsHookEx 將自定義回調函數插入鏈首,優先接收消息。

HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);
  • idHook:WH_KEYBOARD 鍵盤鉤子
  • lpfn:回調函數指針
  • hMod:包含回調函數的 DLL 模塊句柄
  • dwThreadId:0 表示全局鉤子

回調函數必須置於 DLL 中以捕獲所有進程事件。

DLL 核心實現

Hook.h

BOOL installhook();
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);

Hook.cpp

static HHOOK hkb = NULL;
HINSTANCE hins;

BOOL installhook() {
    hkb = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, hins, 0);
    return TRUE;
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (((DWORD)lParam & 0x40000000) && nCode == HC_ACTION) {
        switch (wParam) {
            case '1': sndPlaySound("1.wav", SND_ASYNC); break;
            case '2': sndPlaySound("2.wav", SND_ASYNC); break;
            // ... 0-9, A-Z 等
            case 'A': sndPlaySound("a.wav", SND_ASYNC); break;
            // ...
        }
    }
    return CallNextHookEx(hkb, nCode, wParam, lParam);
}

需鏈接 winmm.lib,包含 mmsystem.h。

導出定義 Hook.def

installhook
KeyboardProc

EXE 調用 DLL

CreateMutex(NULL, FALSE, "KeySound");
if (GetLastError() == ERROR_ALREADY_EXISTS) OnOK();

HINSTANCE hinstDLL = LoadLibrary("Hook.dll");
if (hinstDLL) {
    typedef BOOL (CALLBACK *INSHOOK)();
    INSHOOK instkbhook = (INSHOOK)GetProcAddress(hinstDLL, "installhook");
    instkbhook();
}

進階優化:相對路徑音檔與按鍵名稱獲取

  • DLL 初始化時用 GetModuleFileName 獲取自身目錄,構建 Sound\ 子目錄相對路徑
  • 利用 GetKeyNameText 在測試程式中自動獲取虛擬鍵碼名稱(如 VK_ESCAPE、VK_MENU),避免手工查表

調試提示

  • 確保 Hook.dll、Sound 目錄與 EXE 同級
  • 鏈接錯誤 unresolved external symbol __imp__sndPlaySoundA@8 → 添加 winmm.lib
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved