使用鼠标钩子拦截WM_LBUTTONDOWN消息报错1429如何解决?
错误1429根因
你遇到的错误码1429是因为调用SetWindowsHookEx挂载WH_MOUSE_LL(对应LowLevelMouseProc回调)时传入了非0的线程ID参数。WH_MOUSE_LL是全局低级鼠标钩子,必须传入0作为线程ID参数全局挂载,而且这个钩子不需要将回调函数封装在DLL中,它会把事件投递到调用挂载函数的线程消息队列,要求该线程必须运行正常的消息循环(GetMessage/DispatchMessage),否则钩子不会触发。
当前代码不生效的核心问题
修改回调中的wParam为WM_NULL无法实现拦截,钩子逻辑的拦截规则是:如果要丢弃当前消息,不需要调用CallNextHookEx,直接返回非0值即可,系统会自动终止该消息的向下传递。
可行解决方案
方案1:使用WH_MOUSE_LL全局钩子(无需注入DLL)
适合需要全局拦截、或者不想做DLL注入的场景,调整挂载参数和回调逻辑即可,示例代码如下:
extern "C" __declspec(dllexport) LRESULT CALLBACK mouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode < 0) { // nCode小于0的事件必须传递给下一个钩子 return CallNextHookEx(NULL, nCode, wParam, lParam); } if (nCode == HC_ACTION && wParam == WM_LBUTTONDOWN) { MSLLHOOKSTRUCT* mhs = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam); // 可选:只拦截特定窗口的点击,避免影响全局 HWND clickHwnd = WindowFromPoint(mhs->pt); // 可在这里添加判断逻辑,比如对比窗口类名、标题确认是目标窗口再拦截 // if (IsTargetWindow(clickHwnd)) { return 1; // 直接返回非0,拦截当前左键按下消息 // } } // 其余消息正常传递 return CallNextHookEx(NULL, nCode, wParam, lParam); }
挂载钩子的代码需要按如下规范编写:
// exe内挂载传GetModuleHandle(NULL),DLL内挂载传DLL自身的实例句柄 HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL, mouseHookProc, GetModuleHandle(NULL), 0); if (mouseHook == NULL) { // 处理挂载失败逻辑 } // 挂载钩子的线程必须运行消息循环,否则钩子无法接收事件 MSG msg; while (GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } // 程序退出前卸载钩子 UnhookWindowsHookEx(mouseHook);
方案2:使用WH_MOUSE线程钩子(仅针对目标窗口,无全局影响)
如果你不需要全局拦截,仅需要拦截指定窗口的消息更推荐该方案,不会触发全局钩子的权限限制:
- 先通过
GetWindowThreadProcessId获取目标窗口所属的线程ID - 调用
SetWindowsHookEx时传入WH_MOUSE类型、目标线程ID,钩子函数封装在DLL中 - 回调拦截逻辑和方案1一致,需要拦截时直接返回非0即可,该方案不会报1429错误,拦截效率更高,对其他程序无影响。
内容的提问来源于stack exchange,提问作者user16872085
相关产品推荐
相关产品推荐

