为 WH_MOUSE 设置 WindowsHookEx

Posted

技术标签:

【中文标题】为 WH_MOUSE 设置 WindowsHookEx【英文标题】:SetWindowsHookEx for WH_MOUSE 【发布时间】:2012-06-26 04:52:30 【问题描述】:

我有一些代码可以在全局范围内打印鼠标的坐标(使用 WH_MOUSE_LL)。我的目标是使用 WH_MOUSE 而不是 WH_MOUSE_LL 因为(根据我的阅读)它更快。我在论坛上读过,当使用 WH_MOUSE 时,需要在 DLL 中声明它以实现全局效果,但是,当在程序中使用时,它应该在声明它的应用程序上工作,但它不起作用(它什么都不打印)当我将 WH_MOUSE_LL 更改为 WH_MOUSE 时。这是代码:

#define _WIN32_WINNT 0x0400
#pragma comment( lib, "user32.lib" )

#include <windows.h>
#include <stdio.h>

HHOOK hMouseHook;

LRESULT CALLBACK mouseProc (int nCode, WPARAM wParam, LPARAM lParam)

    MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT *)lParam;
    if (pMouseStruct != NULL)
        if(wParam == WM_LBUTTONDOWN)
        
            printf( "clicked" ); 
        
        printf("Mouse position X = %d  Mouse Position Y = %d\n", pMouseStruct->pt.x,pMouseStruct->pt.y);
    
    return CallNextHookEx(hMouseHook, nCode, wParam, lParam);


DWORD WINAPI MyMouseLogger(LPVOID lpParm)

    HINSTANCE hInstance = GetModuleHandle(NULL);

    // here I put WH_MOUSE instead of WH_MOUSE_LL
    hMouseHook = SetWindowsHookEx( WH_MOUSE_LL, mouseProc, hInstance, NULL );

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

    UnhookWindowsHookEx(hMouseHook);
    return 0;


int main(int argc, char** argv)

    HANDLE hThread;
    DWORD dwThread;

    hThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)MyMouseLogger, (LPVOID) argv[0], NULL, &dwThread);
    if (hThread)
        return WaitForSingleObject(hThread,INFINITE);
    else
        return 1;


【问题讨论】:

某些挂钩将不起作用,除非它们位于 DLL 中。当您的钩子需要被调用并且是一种需要在每个进程内部的钩子时,Windows 会处理加载 DLL 并使其在所有进程中工作。 IIRC,键盘和鼠标钩子都必须在 DLL 中才能在任何地方运行。 "某些挂钩将无法工作,除非它们位于 DLL 中" - 是的,但 WH_MOUSE_LL 和 (WH_KEYBOARD_LL) 不在其中,因为它们运行在安装它们的进程中,而不是在它们挂钩的进程中。 【参考方案1】:
// here I put WH_MOUSE instead of WH_MOUSE_LL
hMouseHook = SetWindowsHookEx( WH_MOUSE_LL, mouseProc, hInstance, NULL );

还必须将第四个参数更改为 GetCurrentThreadId() 以使其成为本地参数。

【讨论】:

嘿,感谢您的关注。我将其更改为: hMouseHook = SetWindowsHookEx( WH_MOUSE, mouseProc, hInstance, GetCurrentThreadId() );但它仍然不起作用(当我将鼠标移到命令行上时它仍然不打印任何东西)。抱歉只是乞求解决方案,但我完全不知道该怎么做。 控制台应用程序并不是测试此类事情的最佳应用程序。控制台窗口处于另一个进程中。如果您想测试,请尝试通过 CreateWindow 创建一个新窗口。 谢谢,我还有一个问题。从我读到的将钩子放入DLL中,它会注入进程。这是否意味着捕获鼠标也可以在我的桌面、菜单启动等上工作?应用程序的标题栏呢?我在互联网上看到过一些有此类问题的帖子,但不知道它们是否因某些原因而失败或存在某种限制(或其他方法)。 应该可以。全局挂钩适用于所有进程,包括 explorer.exe。注意32位DLL只能注入32位进程,64位DLL只能注入64位进程。【参考方案2】:

因为你有一个“main”,我猜你需要把它变成一个 dll 来处理 *_LL 类型以外的消息

Understanding the low-level mouse and keyboard hook (win32)

http://developer-resource.blogspot.com/2008/07/setwindowshookex-example.html有一个dll例子

【讨论】:

以上是关于为 WH_MOUSE 设置 WindowsHookEx的主要内容,如果未能解决你的问题,请参考以下文章

SetWindowsHookEx WH_MOUSE 在 Win7 中的断点处冻结

Sample Golbal WindowsHook KeyBoardHook

Sample Golbal WindowsHook KeyBoardHook

Windows Hook链机制详解

获取IE页面窗口的问题

在两个线程中设置两个鼠标钩子