使用WH_KEYBOARD钩子时,如何判断LowLevelKeyboardProc的按键消息类型?
问题解答
核心错误修正
你这里犯了一个关键错误:WH_KEYBOARD钩子对应的回调函数不是LowLevelKeyboardProc,后者是专门给全局的WH_KEYBOARD_LL钩子用的。WH_KEYBOARD钩子的正确回调函数是KeyboardProc,它的参数定义和你写的完全不同——wParam直接就是WM_KEYDOWN、WM_KEYUP这类消息标识,而不是虚拟键码。
正确的实现方式
要拦截指定线程的按键操作,使用WH_KEYBOARD钩子的正确步骤如下:
- 定义正确的钩子回调函数
KeyboardProc:
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { // 只有nCode为HC_ACTION时才处理消息 if (nCode == HC_ACTION) { // wParam直接就是WM_KEYDOWN/WM_KEYUP/WM_SYSKEYDOWN/WM_SYSKEYUP switch (wParam) { case WM_KEYDOWN: // 处理普通按键按下 break; case WM_KEYUP: // 处理普通按键抬起 break; case WM_SYSKEYDOWN: // 处理系统按键(比如Alt组合键)按下 break; case WM_SYSKEYUP: // 处理系统按键抬起 break; } // 如果要拦截按键,返回非0值;否则调用下一个钩子 // return 1; // 拦截按键 } // 传递消息给下一个钩子 return CallNextHookEx(g->KeyboardHook, nCode, wParam, lParam); }
- 修正钩子的创建代码:
// 注意:SetWindowsHookEx的第三个参数必须是包含钩子过程的模块句柄 // 如果钩子过程在当前EXE中,用GetModuleHandle(NULL)是对的 g->KeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle(NULL), GetWindowThreadProcessId(g->hWnd, NULL));
关于你最初的误解补充
如果你误用了WH_KEYBOARD_LL钩子(全局),它的wParam确实是WM_KEYDOWN/WM_KEYUP这类消息,而虚拟键码是存在KBDLLHOOKSTRUCT的vkCode字段里。但你要拦截指定线程,WH_KEYBOARD才是正确选择,它会只在目标线程的消息队列处理按键消息时触发。
内容的提问来源于stack exchange,提问作者Cesar
相关产品推荐
相关产品推荐

