下面的代码注册了一个低级鼠标钩子来全局监控鼠标事件。
这是我能得到的最简单的工作示例。
使用 VC++ 2010 编译:cl test.cpp /link /entry:mainCRTStartup /subsystem:windows
#include <windows.h>
HWND label1 ;
//THE HOOK PROCEDURE
LRESULT CALLBACK mouseHookProc(int aCode, WPARAM wParam, LPARAM lParam){
static int msgCount = 0 ;
static char str[20] ;
SetWindowText( label1, itoa(++msgCount, str, 10) ) ;
return CallNextHookEx(NULL, aCode, wParam, lParam) ;
}
int main(){
/**/// STANDARD WINDOW CREATION PART //////////////////////////////////////////////////////
/**/
/**/ WNDCLASSEX classStruct = { sizeof(WNDCLASSEX), 0, DefWindowProc, 0, 0, GetModuleHandle(NULL), NULL,
/**/ LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_BTNFACE+1), NULL, "winClass", NULL } ;
/**/ RegisterClassEx(&classStruct) ;
/**/
/**/ HWND mainWin = CreateWindow("winClass", "", 0, 200,200, 100,100, NULL, NULL, NULL, NULL) ;
/**/ ShowWindow(mainWin, SW_SHOWDEFAULT) ;
/**/
/**/ label1 = CreateWindow("static", "0", WS_CHILD, 5,5, 80,20, mainWin, NULL, NULL, NULL) ;
/**/ ShowWindow(label1, SW_SHOWNOACTIVATE) ;
/**/
/**/// END OF WINDOW CREATION PART ////////////////////////////////////////////////////////
//HOOK INSTALATION
HHOOK hookProc = SetWindowsHookEx(WH_MOUSE_LL, mouseHookProc, GetModuleHandle(NULL), 0) ;
//MESSAGE LOOP
MSG msg ;
while( GetMessage(&msg, NULL, 0, 0) ){
TranslateMessage(&msg) ;
DispatchMessage(&msg) ;
}
UnhookWindowsHookEx(hookProc) ;
}
这是基本的一个线程、一个窗口、一个消息泵示例。除了鼠标钩。
我怀疑这段代码所做的与我在 SO、MSDN、论坛、博客等中反复阅读的两件事相矛盾。
全局挂钩程序必须驻留在 DLL
MSDN 文档中,以SetWindowsHookEx
通过以下方式确认这一点:如果 dwThreadId 参数为零,则 lpfn 参数必须指向 DLL 中的挂钩过程
GUI 线程(带有消息泵的线程)不能被中断,因为
GetMessase
' 的等待状态是不可警告的。这意味着当GetMessage
阻塞等待更多消息时,它无法接收到中断其等待状态的信号。
但是,这里看不到任何 DLL,而且钩子过程必须中断线程,否则程序将无法运行,并且确实可以(我假设该程序中只有一个线程)。
所以要么我完全误解了这两点,要么这段代码的工作方式与我所期望的异步过程调用方法不匹配。
不管怎样,我对这里发生的事情一无所知。
你能解释一下这段代码是如何工作的吗?
是单线程程序吗?
钩子程序是否中断线程?
以上两点中的任何一点都是真的吗?