低级鼠标钩子 - 鼠标冻结在断点上

问题描述 投票:0回答:3

我想自己绘制和移动我的窗口(使用 Chromium 嵌入式框架)。 为此,当鼠标移动到窗口之外时,我需要一个全局回调 - 所以我安装了一个低级别的鼠标钩子:

hMouseLLHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)mouseHookProc, hInstance, NULL);

钩子简单地捕获鼠标事件并调用“CallNextHookEx”。这里没有问题,一切都按预期进行。 我现在的问题是:如果调试器中断或抛出异常,我将无法再移动鼠标..

我尝试在另一个线程中处理钩子,如下所示:

HANDLE mouseProcHandle = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)mouseProcessor, NULL, NULL, &dwMouseProcThread);

DWORD WINAPI Win32Application::mouseProcessor(LPVOID lpParm) {
    hMouseLLHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)mouseHookProc, ((Win32Application*)Application::getInstance())->hInstance, NULL);

    MSG message;
    while (GetMessage(&message, NULL, 0, 0)) {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }

    UnhookWindowsHookEx(hMouseLLHook);
    return 0;
}

但这也并不能解决问题。有解决办法、解决方案或其他方法来做到这一点吗? 另外,我认为低级挂钩可能不是必要的,因为我只需要了解移动情况,如果我是最后一个,那么系统/其他进程可以处理该移动首先鼠标回调。

c++ windows visual-studio visual-c++ chromium-embedded
3个回答
7
投票

为了更清楚地说明这一点:当您拦截所有鼠标移动事件时,它们最终都会出现在您的钩子中,钩子可以修改或吞噬它们。因此,系统为每个鼠标移动事件调用您的钩子,并等待直到您的钩子例程完成,直到它再次为下一个挂起的鼠标移动事件调用您的钩子。

猜猜当您在钩子事件中闯入调试器时会发生什么?在完成钩子例程之前,不再有鼠标事件。通常情况下,您可以使用这样的中央挂钩来关闭整个系统。但幸运的是,Windows 确实预见到了坏钩子。 您会注意到,超时后系统会再次响应鼠标事件。我的猜测是,当你的钩子挂起一次时,Windows 就会简单地删除它。

现在关于调试:安全地进入调试器的唯一方法是在陷入困境后永远不要触摸鼠标。不太实用。唯一的出路是跟踪有趣的事情并查看日志文件在钩子内发生了什么。 如果您正在寻找如何挂钩鼠标和键盘事件的示例代码,您可以看看这里:

http://etwcontroler.codeplex.com/SourceControl/latest#ETWControler/Hooking/Hooker.cs


3
投票

当你的调试器停止整个程序(它的所有线程)
如果使用钩子,可能没有解决方法。
不太准确,但您可以在线程中轮询 GetCursorPos。


0
投票

这是一个老问题,但可能有人会寻找解决方案。

您可以在函数的最开始处使用断点调用 UnhookWindowsHookEx,然后在函数的最后调用 SetWindowsHookEx。如果函数在中间某处返回,您还应该在返回之前调用 SetWindowsHookEx。如果函数内部有异常处理程序,还需要在其中调用SetWindowsHookEx

对我来说这个方法效果很好,在功能调试过程中没有任何冻结问题。

© www.soinside.com 2019 - 2024. All rights reserved.