c ++:如何在任何地方捕获鼠标点击

GSt*_*Sta 11 c++ mouse winapi

我遇到了我正在编写的应用程序,我需要监视鼠标点击.

点击可能发生在屏幕上的任何地方,而不是在应用程序窗口内,对于每次点击,我必须传递消息(执行操作或其他内容).

我环顾四周,阅读了一些像使用的建议

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Run Code Online (Sandbox Code Playgroud)

但我没有成功.

有没有人知道如何实现我需要的东西?

Eug*_*its 10

您需要按照MSDN中的说明设置鼠标挂钩.

请注意,在您的情况下,钩子需要是全局的.这意味着您需要在DLL中实现处理函数,该函数将被加载到系统中接收鼠标消息的所有进程中.这样的DLL将使用某些进程间通信(IPC)机制(如共享内存)或通过从DLL 发布(未发送)到主应用程序的Windows消息与主应用程序进行通信.

您可以使用此CodeProject文章中的源代码作为指南.

更新:根据Chris的更正,我应该注意上面适用于同步的"常规"鼠标钩子.低级挂钩不需要位于DLL中,但它具有某些限制,这些限制在相应的MSDN文章中有所描述.

  • 如果使用低级别的dll,则不需要dll.我可以从经验中确认一下. (6认同)
  • @EugeneMayevski'EldoSCorp;同意; 我实际上只是指出,如果代码编写得当,LL 钩子的时间限制不应该成为问题。(如果有人遇到了这个问题,那么他们一开始就做错了钩子!)我的看法是,进程内可以有更好的性能,但由于跨进程问题,编写起来比较棘手;而 LL 的开销更大,但启动和运行要简单得多。对于新手来说,我建议首先使用 LL 钩子来使用该钩子 - 否则使用单独的 DLL,他们将花费相当多的时间来弄清楚跨进程的东西。 (2认同)

小智 6

好吧,我真的不知道你是否解决了你的问题.希望如此.但是今天我遇到了同样的麻烦并且搜索我找到了一种非常容易实现的方法.

所以你在这里:

int keyPressed(int key){
    return (GetAsyncKeyState(key) & 0x8000 != 0);
}

int main(){
    while(1){
        if(keyPressed(VK_LBUTTON)){
            printf("%s\n","Click izquierdo");
        }
        if(keyPressed(VK_RBUTTON)){
            printf("%s\n","Click Derecho");
        }
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案的关键是函数GetAsyncKeyState(key),其中键出这里出现的任何代码https://msdn.microsoft.com/en-us/library/dd375731(VS.85).aspx


Aur*_*rus 5

你可以使用SetWindowsHookEx

这是一个小样本:

#define _WIN32_WINNT 0x0500
#include <windows.h>

HHOOK MouseHook;

LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam){

        PKBDLLHOOKSTRUCT k = (PKBDLLHOOKSTRUCT)(lParam);
        POINT p;


        if(wParam == WM_RBUTTONDOWN)
        { 
          // right button clicked 
          GetCursorPos(&p);
        }

}

void StayAlive(){
        while(_getch() != 27) { }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nShowCmd){
        FreeConsole();

        MouseHook = SetWindowsHookEx(WH_MOUSE_LL,MouseHookProc,hInstance,0);
        StayAlive();

        UnhookWindowsHookEx(MouseHook);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 好奇,这个有用吗?LL 钩子需要消息循环,并且我无法立即回忆起 _getch() 是否在幕后泵送消息以允许消息传递 - 大多数控制台风格的 API 都没有。MessageBox() 是另一种快速但肮脏的替代方法,它确实可以泵送消息,并且在最初使用这些 API 时非常有用。 (2认同)