这是适用于我的WH_KEYBOARD_LL代码。
#include <Windows.h>
#include <iostream>
using namespace std;
HHOOK _hook;
KBDLLHOOKSTRUCT kbdStruct;
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
cout << nCode;
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void SetHook() {
if (!(_hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0))) {
cout << "SetWindowsHookEx Fail";
}
}
void ReleaseHook() {
UnhookWindowsHookEx(_hook);
}
int main() {
SetHook();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
// do something here
}
return 0;
}
但是,当我将SetWindowsHookEx行更改为if (!(_hook = SetWindowsHookEx(WH_KEYBOARD, HookCallback, NULL, GetCurrentThreadId())))
时,它不起作用。
我有3个问题。
如何让WH_KEYBOARD
挂机工作?
如果我用cout
替换循环内的注释,我就看不到任何控制台输出。所以我很困惑,循环的主体是否完全执行?
我还在GetMessage
的循环中读到,我应该添加对DispatchMessage
的调用。 DispatchMessage
和CallNextHookEx
之间的区别是什么?我阅读了关于它们的文档,但无法理解。
答案 0 :(得分:1)
GetMessage()
永远不会返回,因为如果没有与进程关联的窗口句柄,则没有关联的消息队列,也不会发生消息处理魔法(除非您手动发布消息)。这很疯狂,但我想它解释了操作系统的名称。引自GetMessage()
:
GetMessage函数检索与窗口关联的消息 由hWnd参数或其任何子项
标识
您可以WH_KEYBOARD_LL
工作,因为无论GetMessage()
如何都会调用它。您不会接听WH_KEYBOARD
次来电,因为仅在GetMessage()
正常运作时才会调用。
<强> WH_KEYBOARD_LL 强>
WH_KEYBOARD_LL挂钩使您可以监视键盘输入事件 即将发布在线程输入队列中。有关更多信息,请参阅 LowLevelKeyboardProc回调函数。
<强> WH_KEYBOARD 强>
WH_KEYBOARD挂钩使应用程序能够监控消息流量 对于要返回的WM_KEYDOWN和WM_KEYUP消息 GetMessage或PeekMessage函数。您可以使用WH_KEYBOARD钩子 监控发布到消息队列的键盘输入。
Q&安培; A:
如何让WH_KEYBOARD挂钩工作?
您需要创建一个窗口。即使是消息框也可以。甚至隐藏。
如果我用循环替换循环内的注释,我就不会看到任何控制台输出。所以我很困惑,循环的身体 执行完毕?
没有。因为GetMessage()
永远阻止。因为没有收到的消息。
我还读到了在GetMessage循环中,我应该添加对DispatchMessage的调用。 DispatchMessage和CallNextHookEx之间的区别是什么?我阅读了关于他们两个的文档,但无法理解。
这两个功能是正交的。
使用GetMessage()
从队列中删除邮件后,您需要调用DispatchMessage()
将邮件传递给与该窗口关联的WindowProc
。否则WindowProc
没有收到它。
CallNextHookEx
会将消息传递给链中的下一个挂钩。
<子> 的此外:强> 子>
<子>
(1)您不应将_hook
传递给CallNextHookEx
。无论如何,第一个参数被忽略。传递钩柄只是令人困惑。
子>
<子> (2)您应该始终执行适当的错误检查。 子>
<子> (3)不要忘记解开钩子。 子>
答案 1 :(得分:1)
根据KeyboardProc
callback function文档:
与
SetWindowsHookEx
函数一起使用的应用程序定义或库定义的回调函数。 只要应用程序调用{{1}}或GetMessage
函数并且有待处理的键盘消息(PeekMessage
或WM_KEYUP
),系统就会调用此函数
您的WM_KEYDOWN
回调无法正常工作,因为挂钩的线程正在调用WH_KEYBOARD
但未收到任何GetMessage()
或WM_KEYUP
条消息。这些是窗口消息,但是没有可视窗口供他们发布。
WM_KEYDOWN
挂钩在较低级别运行,因此不需要挂钩线程调用WH_KEYBOARD_LL
来接收窗口消息。根据{{3}}文档:
与
(Get|Peek)Message()
函数一起使用的应用程序定义或库定义的回调函数。 每次新的键盘输入事件即将发布到线程输入队列时,系统都会调用此函数。