使用SetWindowsHookEx挂钩键盘消息的问题

时间:2011-07-23 16:09:03

标签: c++ visual-studio-2008 winapi

我试图在没有任何成功的情况下挂钩键盘消息。

我创建了一个测试控制台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。

我在想什么?

2 个答案:

答案 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。