我试图在没有任何成功的情况下挂钩键盘消息。
我创建了一个测试控制台win32 app:
int _tmain(int argc, _TCHAR* argv[])
{
HOOKPROC hHookProc;
HINSTANCE hinstDLL;
HHOOK hHook;
hinstDLL = LoadLibrary(TEXT("pathtodll\\KeyHook.dll"));
hHookProc= (HOOKPROC)GetProcAddress(hinstDLL, "HookProc");
hHook = SetWindowsHookEx(
WH_KEYBOARD,
hHookProc,
hinstDLL,
0);
while (1) {}
return 0;
}
我还使用HookProc函数创建了一个测试win32 dll:
extern __declspec(dllexport) LRESULT CALLBACK HookProc(
int nCode,
WPARAM wParam,
LPARAM lParam
)
{
// process event
//...
MessageBox( NULL,
TEXT("OK"),
TEXT("OK"),
MB_OK);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
所有内容编译都很好但是当我尝试调试时,似乎HookProc从未被调用过。实际上在Win 7中,当我按任意键时应用程序挂起,而在Win Xp中则不会调用HookProc。我得到的不是NULL hinstDLL,hHookProc,hHook。
我在想什么?
答案 0 :(得分:1)
在调用SetWindowsHookEx()
之后,不要执行空白while循环,而是通过Peek/GetMessage()
尝试让循环泵调用调用线程的消息队列。一些钩子在安装它们的线程的上下文中运行,因此操作系统必须能够在需要时切换到该线程。
答案 1 :(得分:0)
这里有几个问题:
while (1) {}
不要这样做:你的代码现在有一个繁忙的(无限的)循环,它会有效地使应用程序无响应(并且可能使整个桌面看起来也很迟钝)。 GetMessage在这里工作的原因很简单,因为它将控制权交还给操作系统,这将使线程处于休眠状态而不是忙碌地运行。你可能只是通过调用Sleep(...)来获得相同的效果,它也会将控制权返回给操作系统但没有泵送消息。对于测试代码,像getchar()这样的东西在这里可以正常工作,它会优雅地阻塞,直到你在控制台窗口中按Enter键。 MessageBox()也可以在这里工作。
extern __declspec(dllexport) LRESULT CALLBACK HookProc(
{
MessageBox( NULL,
TEXT("OK"),
TEXT("OK"),
MB_OK);
另一个问题:你通常不想在钩子回调中做任何“复杂”的事情 - 只需要做最小的处理消息,然后尽快返回。你肯定不想阻止,这就是MessageBox的作用。出于调试目的,可以使用OutputDebugString()或其他一些不阻塞的面向调试的API。