我在带有 Visual Studio 2019 的 Windows7 上使用 Windows API。
我正在尝试设置一个低级键盘挂钩并读取控制台的键输入,为此我使用函数:HHOOK SetWindowsHookExA( [in] int idHook, [in] HOOKPROC lpfn, [in] HINSTANCE hmod, [in] DWORD dwThreadId )
和参数:WH_KEYBOARD_LL
所以我可以监视键盘事件。
这是我的主要功能:
int main()
{
...
HHOOK keyBoardHook = SetWindowsHookExW(WH_KEYBOARD_LL, keyboardHook, NULL, 0);
MSG message;
while (true)
{
while(PeekMessage(&message, NULL, 0, 0, PM_REMOVE) != 0)
{
DispatchMessage(&message);
}
}
...
UnhookWindowsHookEx(keyBoardHook);
return 0;
}
这是回调实现:
LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
{
KBDLLHOOKSTRUCT* keyData = (KBDLLHOOKSTRUCT*)lParam;
if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
fileHandler.addStr(keyHandler.translate(keyData,true,topWindowThreadId));
}
else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)
{
fileHandler.addStr(keyHandler.translate(keyData,false,topWindowThreadId));
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
这两个变量如何工作不是这里的问题,而只是知道在回调中keyHandler
翻译消息并将fileHandler
结果打印到文件中。
问题来了。回调接收:
当我按下一个键时的按键事件
我释放时的按键事件
当我按住按键时重复按键事件
VK_LCONTROL
焦点窗口更改时的控制键向上事件
为什么会这样?据我所知,MSDN 文档中从未提及此行为。如果我从控制台窗口或任何窗口切换到任何其他窗口,则会生成此事件[left control up]
并由我的keyHandler
!
现在为了确保我的代码没有问题,我将回调更改为:
LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
{
KBDLLHOOKSTRUCT* keyData = (KBDLLHOOKSTRUCT*)lParam;
if (keyData->vkCode == VK_LCONTROL)
{
printf("CTRL");
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
并且每当我更改焦点窗口时仍然CTRL
会打印到控制台,请注意仅VK_LCONTROL
生成并且 wParam 始终WM_KEYUP
这不应该发生!
我尝试分析和修改我的代码,尝试从主函数中删除所有内容,直到它看起来就像上面的示例一样,甚至重新启动计算机以检查它是否是内部问题,没有任何帮助。当在网上搜索具有类似问题的类似帖子时,我发现完全没有,这使得它更加混乱。
更新
我尝试从 GitHub 编译别人的键盘挂钩相关代码,同样的问题.. 这正常吗?为什么没有记录?