使用 SetWindowsHookEx 时灵敏度下降

Posted

技术标签:

【中文标题】使用 SetWindowsHookEx 时灵敏度下降【英文标题】:Sensitivity drops when using SetWindowsHookEx 【发布时间】:2021-07-12 14:27:59 【问题描述】:

当我将钩子放在鼠标上时,我会周期性地失去灵敏度,它会增加约 0.3 秒(大约两倍)。我怎样才能解决这个问题? 我的处理程序代码:

LRESULT CALLBACK mouseProc(int Code, WPARAM wParam, LPARAM lParam)
MOUSEHOOKSTRUCT* pMouseStruct = (MOUSEHOOKSTRUCT*)lParam;
if (pMouseStruct != nullptr) 
    switch (wParam) 
    case WM_LBUTTONDOWN:
        std::cout << "WM_LBUTTONDOWN";
        break;
    case WM_LBUTTONUP:
        std::cout << "WM_LBUTTONUP";
        break;
    case WM_RBUTTONDOWN:
        std::cout << "WM_RBUTTONDOWN";
        break;
    case WM_RBUTTONUP:
        std::cout << "WM_RBUTTONUP";
        break;
    default:
        break;
    

return CallNextHookEx(NULL, Code, wParam, lParam);

我是这样放的:

HHOOK hook = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, NULL, 0);

MSG message;
while (GetMessage(&message, NULL, 0, 0) > 0)

    TranslateMessage(&message);
    DispatchMessage(&message);


UnhookWindowsHookEx(hook);

【问题讨论】:

两件事 - (1) "...如果 nCode 小于零,则挂钩过程必须将消息传递给 CallNextHookEx 函数而不进行进一步处理..." docs.microsoft.com/en-us/previous-versions/windows/desktop/… 和 (2) std::cout &lt;&lt; 可能会同步。 除了理查德所说的,请注意您使用std::cout。对于像鼠标这样需要非常长的响应时间的东西来说,它非常慢。 附注:WH_MOUSE_LL 使用 MSLLHOOKSTRUCTWH_MOUSE 使用 MOUSEHOOKSTRUCT。它们不是一回事,所以不要把它们混为一谈。 【参考方案1】:

您在这段代码中失去了敏感性,因为std::cout 非常慢。您需要快速响应此挂钩,否则您显然会失去敏感性。

如果您确实需要登录您的钩子,请使用 spdlog 之类的东西并异步记录所有内容。

此外,正如理查德在 cmets 中提到的,您在钩子开始时需要这样的东西:

if (nCode < 0) // do not process message 
    return CallNextHookEx(hhook, nCode, wParam, lParam); 

【讨论】:

OutputDebugString 是异步的,不会引入另一个依赖项。 我可以通过CreateThread运行代码来提高速度吗?这会有帮助吗? @IInspectable 你确定它是异步的吗?因为我在 msdn 中没有看到任何地方。 @Elberer 你不能为你的钩子使用线程。问题是记录部分。您需要以一种快速异步的方式登录。您可以自己编写此类日志记录,使用类似的 API 或使用其他库。 一旦OutputDebugString 将其有效负载复制到共享缓冲区中,代码将继续执行。它不会等待调试器观察输出。甚至可能没有调试器在监听。当然,在保护共享缓冲区时会涉及到一些同步,尽管你必须特别不幸地遇到这种争用。 Understanding Win32 "OutputDebugString" 有内部细节。

以上是关于使用 SetWindowsHookEx 时灵敏度下降的主要内容,如果未能解决你的问题,请参考以下文章

SetWindowsHookEx WH_KEYBOARD_LL 问题锁屏

在我的线程上下文中调用“SetWindowsHookEx”函数

SetWindowsHookEx 不适用于线程 ID

如何使用 SetWindowsHookEx api 锁定 CTRL+ALT+DEL?

SetWindowsHookEx 并单击表单冻结时的最小化/最大化/关闭按钮

SetWindowsHookEx 在快速输入或键盘按钮按住时冻结