一、需求说明
正常情况下,Qt获取鼠标事件都是获取窗口内的鼠标事件,当窗口、控件 获取焦点之后,点击窗口内的控件,Qt都可以获取到鼠标事件。 如果窗口没有获取到焦点,或者 点击软件范围外的其他地方,Qt正常的事件捕获就无法监听鼠标的动作了。
现在的需求是: 需要在软件之外,任何地方点击鼠标,Qt程序里都能获取到数据事件,实现全局鼠标事件侦听。
这个可以利用win32的API接口SetWindowsHookEx
来实现侦听。
具体实现代码看下面。
二、实现代码
侦听全局鼠标事件用到了windows系统API函数。
完整的测试代码如下:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <Windows.h>
#include <QDebug>
#pragma execution_character_set("utf-8")
#pragma comment(lib, "user32.lib")
HHOOK hHook = NULL;
using namespace std;
/*
WM_MOUSEMOVE = 0x200
WM_LBUTTONDOWN = 0x201
WM_LBUTTONUP = 0x202
WM_LBUTTONDBLCLK = 0x203
WM_RBUTTONDOWN = 0x204
WM_RBUTTONUP = 0x205
WM_RBUTTONDBLCLK = 0x206 双击事件
WM_MBUTTONDOWN = 0x207
WM_MBUTTONUP = 0x208
WM_MBUTTONDBLCLK = 0x209
WM_MOUSEWHEEL = 0x20A
WM_XBUTTONDOWN = 0x20B
WM_XBUTTONUP = 0x20C
WM_XBUTTONDBLCLK = 0x20D
WM_MOUSEHWHEEL = 0x20E
*/
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
switch(wParam)
{
case WM_LBUTTONDOWN: //鼠标左键按下
qDebug() << "鼠标左键按下";
break;
case WM_RBUTTONDOWN://鼠标右键键按下
qDebug() << "鼠标右键键按下";
break;
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
hHook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, NULL, 0);
if (hHook == NULL)
{
qDebug() << "Hook failed";
}
else
{
qDebug() << "Hook Success";
}
}
Widget::~Widget()
{
delete ui;
}
三、利用win32-API模拟鼠标事件发送
3.1 mouse_event函数
cpp
VOID WINAPI mouse_event(
_In_ DWORD dwFlags,
_In_ DWORD dx,
_In_ DWORD dy,
_In_ DWORD dwData,
_In_ ULONG_PTR dwExtraInfo
);
dwFlags的常用选项如下:
cpp
MOUSEEVENTF_ABSOLUTE 是否使用绝对坐标
MOUSEEVENTF_LEFTDOWN 鼠标左键按下
MOUSEEVENTF_LEFTUP 鼠标左键松开
MOUSEEVENTF_MIDDLEDOWN 鼠标中键按下
MOUSEEVENTF_MIDDLEUP 鼠标中键松开
MOUSEEVENTF_MOVE 鼠标移动
MOUSEEVENTF_RIGHTDOWN 鼠标右键按下
MOUSEEVENTF_RIGHTUP 鼠标右键按下
MOUSEEVENTF_WHEEL 鼠标滑轮
3.2 包含的头文件与库文件
cpp
#include <Windows.h>
#pragma comment(lib, "user32.lib")
3.3 使用案例
cpp
使用鼠标模拟单击事件
int x = 50;
int y = 50;
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN,x, y, 0, 0);
双击事件
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN,x, y, 0, 0);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP,x, y, 0, 0);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN,x, y, 0, 0);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP,x, y, 0, 0);
滚轮事件,delta为滚轮的值
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_WHEEL,p.x(), p.y(), delta, 0);