為協助長輩練習盲打,開發一款按鍵即發音的小工具:系統全局攔截鍵盤事件,播放對應音檔。
SetWindowsHookEx 將自定義回調函數插入鏈首,優先接收消息。
HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);
idHook:WH_KEYBOARD 鍵盤鉤子lpfn:回調函數指針hMod:包含回調函數的 DLL 模塊句柄dwThreadId:0 表示全局鉤子回調函數必須置於 DLL 中以捕獲所有進程事件。
BOOL installhook(); LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
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。
installhook KeyboardProc
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();
}
GetModuleFileName 獲取自身目錄,構建 Sound\ 子目錄相對路徑GetKeyNameText 在測試程式中自動獲取虛擬鍵碼名稱(如 VK_ESCAPE、VK_MENU),避免手工查表Hook.dll、Sound 目錄與 EXE 同級unresolved external symbol __imp__sndPlaySoundA@8 → 添加 winmm.lib