С++: как поймать клики мыши везде, где они происходят

Я застрял в приложении, которое я пишу, где мне нужно следить за щелчками мыши.

Клики могут происходить в любом месте экрана, а не в окне приложения, и для каждого клика я должен передать сообщение (выполнить действие или что-то еще).

Я огляделся и прочитал несколько советов, как использовать

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

но я не увенчался успехом.

Есть ли у кого-нибудь идея о том, как реализовать то, что мне нужно?

Ответ 1

Вам нужно установить крючок мыши, как описано в MSDN.

Обратите внимание, что в вашем случае крючок должен быть глобальным. Это означает, что вам нужно реализовать функцию обработчика в DLL, которая будет загружена во все процессы в системе, которые получают сообщение мыши. Такая DLL будет связываться с вашим основным приложением, используя механизм межпроцессного взаимодействия (IPC), такой как разделяемая память, или через сообщения Windows, отправленные (не отправленные) из DLL в основное приложение.

В качестве руководства вы можете использовать исходный код эту статью CodeProject.

Обновление: согласно исправлению Криса, я должен отметить, что выше применимо к "регулярному" крючку мыши, который является синхронным. Ловушку низкого уровня не нужно размещать в DLL, но она имеет определенные ограничения, которые описаны в соответствующей статье MSDN.

Ответ 2

Вы можете использовать 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;
}

Ответ 3

Хорошо, я действительно не знаю, решили ли вы свою проблему. Я надеюсь, что это так. Но сегодня у меня была такая же проблема, и я искал, что нашел способ сделать это очень легко.

Итак, вот вы:

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;
}

Ключом этого решения является функция GetAsyncKeyState (key), где ключ любого из кодов, которые появляются здесь https://msdn.microsoft.com/en-us/library/dd375731(VS.85).aspx

Ответ 4

LRESULT CALLBACK WndProc(...), поскольку это название предлагает (конкретный) процессор окна (сообщения), где вы можете анализировать и отвечать на сообщения в очереди, которые были отложены системой для вашего пользовательского определения обратного вызова для дальнейшей обработки.

Так как вы хотите обнаруживать и воздействовать на щелчки мыши в любом месте экрана, как подсказывает крис в комментариях, один из способов заключается в том, чтобы подключить себя к системе, вызвав SetWindowsHookEx(), который довольно подробен в своем самом определении - он позволяет вы отслеживаете происходящее в системе и передаете эту информацию обратно в ваше приложение.

Это синтаксис, который вам нужно использовать, чтобы получить

HHOOK WINAPI SetWindowsHookEx(
  __in  int idHook,
  __in  HOOKPROC lpfn,
  __in  HINSTANCE hMod,
  __in  DWORD dwThreadId
);

Он принимает определенный идентификатор hook, который в основном немного #defines, который сообщает функции, какие сообщения вы хотите получать со всей системы, вы передаете ей обратный вызов, как и WndProc, но на этот раз это означало для обработки входящих сообщений относительно системы. hMod просто ссылается на дескриптор приложения или DLL, в котором находится только что упомянутый обратный вызов функции proc. Последний относится к потокам, которые в настоящее время выполняются в системе, устанавливая это значение 0 или NULL извлекает сообщения для всех существующих потоков.

Важно:

Обратите внимание, что пример Aurus, вызывающий SetWindowsHookEx, специфичен для процесса, который представляет собой причудливое слово, связанное с реальным приложением, вместо библиотеки DLL, которая может быть добавлена ​​к нескольким процессам в системе (глобальная) и возвращать информацию к вашему приложению. Было бы разумно потратить время и усилия на исследование рекомендованного Евгения метода вместо этого силового подхода, полезного только для экспериментов. Это немного "сложнее", но вознаграждение стоит.

Меньше работа не всегда лучше или предпочтительнее.