С++: как поймать клики мыши везде, где они происходят
Я застрял в приложении, которое я пишу, где мне нужно следить за щелчками мыши.
Клики могут происходить в любом месте экрана, а не в окне приложения, и для каждого клика я должен передать сообщение (выполнить действие или что-то еще).
Я огляделся и прочитал несколько советов, как использовать
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, которая может быть добавлена к нескольким процессам в системе (глобальная) и возвращать информацию к вашему приложению. Было бы разумно потратить время и усилия на исследование рекомендованного Евгения метода вместо этого силового подхода, полезного только для экспериментов. Это немного "сложнее", но вознаграждение стоит.
Меньше работа не всегда лучше или предпочтительнее.