2011-07-23 26 views
0

我试图挂钩键盘消息没有任何成功。使用SetWindowsHookEx钩住键盘消息的问题

我创建一个测试控制台的Win32应用程序:

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。

我在误解什么?

回答

1

而不是在调用SetWindowsHookEx()之后执行空白while循环,而不是通过Peek/GetMessage()而是通过循环泵调用线程的消息队列。一些钩子在安装它们的线程的上下文中运行,因此操作系统必须能够在需要时切换到该线程。

+0

它的工作原理:P但我不能完全理解为什么:( – Blim

+0

就像我说过的,一些钩子在安装它们的线程的上下文中运行,当调用这样一个钩子时,为了切换到正确的线程上下文,操作系统使用线程的消息队列,因此线程必须定期为新消息抽取消息队列,以便钩子可以运行。 –

+0

问题在于GetMessage()永远不会返回,但就我而言,它会创建我试图找到一些解释所有这些东西的文档,但我找不到具体的东西,关于钩子的msdn文档的部分没有提到需要消息队列的东西。 – Blim

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是要走的路。