钩子和线程,鼠标阻塞
hooks and threads, mouse blocking
#include <windows.h>
#include <process.h>
HWND MainHwnd;
HHOOK MouseHook;
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
static wchar_t szAppName[]=L"hooks";
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
wndclass.cbSize=sizeof(wndclass);
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;
wndclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION);
RegisterClassEx(&wndclass);
MainHwnd=hwnd=CreateWindow(szAppName,L"hooks",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_MAXIMIZE);
UpdateWindow(hwnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK LowLevelMouseProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if (nCode==HC_ACTION)
((LPMSLLHOOKSTRUCT)lParam)->flags=0;
return CallNextHookEx(NULL,nCode,wParam,lParam);
}
void thread(void *param)
{
for (int i=0;i<3;i++)
{
UnhookWindowsHookEx(MouseHook);
MouseHook=SetWindowsHookEx(WH_MOUSE_LL,reinterpret_cast<HOOKPROC>(LowLevelMouseProc),(HINSTANCE)GetWindowLong(MainHwnd,GWL_HINSTANCE),NULL);
for (int j=0;j<100;j++)
{
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE, (j)*(65535.0/500),(j)*(65535.0/500),0,0);
Sleep(10);
}
Sleep(2000);
}
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch(iMsg)
{
case WM_CREATE:
{
MouseHook=SetWindowsHookEx(WH_MOUSE_LL,reinterpret_cast<HOOKPROC>(LowLevelMouseProc),(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
_beginthread(thread,0,0);
return 0;
}
case WM_PAINT:
{
hdc=BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return 0;
}
case WM_DESTROY:
UnhookWindowsHookEx(MouseHook);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,iMsg,wParam,lParam);
}
我用_beginthread
创建线程。此线程模拟鼠标的移动并调用Sleep(2000)
。模拟线程中的移动后,我无法移动鼠标。但是,如果我在void thread(void *param)
中评论这些行
UnhookWindowsHookEx(MouseHook);
MouseHook=SetWindowsHookEx(WH_MOUSE_LL,reinterpret_cast<HOOKPROC>(LowLevelMouseProc),(HINSTANCE)GetWindowLong(MainHwnd,GWL_HINSTANCE),NULL);`
程序将正常工作,无需鼠标"阻止"。每个人都能解释一下原因吗?
调用 SetWindowsHookEx(( 来设置低级鼠标挂钩的线程必须泵送消息循环。 必需的,以便 Windows 可以调用您注册的回调,以便它可以通知您鼠标消息。 这是你的问题,你启动的线程设置了一个钩子,但没有泵送消息循环。
Windows 可以防止此类行为异常的程序,当它必须等待太长时间才能进行回调时,它会自动销毁钩子。 但是您的线程休眠 2 秒,不足以触发超时。 然后调用 UnhookWindowsHookEx(( 来解锁 Windows。 但马上又上钩了。
在该线程中调用 SetWindowsHookEx(( 是没有意义的。 只需删除它,您在主线程中设置的钩子将正常运行。 顺便说一句,通常很难看到该线程的重点。
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++中的线程池
- 线程之间的布尔停止信号
- 为什么std::async使用同一个线程运行函数
- 用于矢量处理的多个线程
- 如何在后台线程上正确设置全局鼠标挂钩
- 钩子和线程,鼠标阻塞