600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Qt实现全局鼠标事件监听器-Windows

Qt实现全局鼠标事件监听器-Windows

时间:2021-03-14 22:07:43

相关推荐

Qt实现全局鼠标事件监听器-Windows

Qt实现全局鼠标事件监听器-Windows版🍇

文章目录

Qt实现全局鼠标事件监听器-Windows版🍇1、概述🍈2、实现效果🍉3、实现方式🍊4、关键代码🍋5、源代码🍌

1、概述🍈

Qt版本:V5.12.5兼容系统: Windows:这里测试了Windows10,其它的版本没有测试;Linux:这里测试了ubuntu18.04、20.04,其它的没有测试;Mac:等啥时候我有了Mac电脑再说。
有时候我们想获取到【系统全局鼠标事件】,使用Qt的鼠标事件、事件过滤器之类的都无法实现,因为当鼠标移出当前窗口或者当前窗口失去焦点、窗口最小化了就无法获取到鼠标事件了;而Windows下想要监听到全局鼠标事件就需要使用到Windows的低级鼠标钩子来实现;关于Windows的鼠标钩子API文档可以看微软官网SetWindowsHookExW ;在这个类中通过Windows鼠标钩子API监听到全局鼠标事件;然后将监听到的鼠标事件映射为QMouseEvent事件,便于在Qt里面使用。

2、实现效果🍉

3、实现方式🍊

使用SetWindowsHookExW()函数挂钩低级鼠标钩子;通过回调函数LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)监听到全局鼠标事件;wParam参数表示信号类型: WM_LBUTTONDOWN:鼠标左键按下WM_LBUTTONUP:鼠标左键抬起WM_MOUSEMOVE:鼠标移动WM_MOUSEWHEEL:鼠标滚轮WM_MOUSEHWHEEL:鼠标的水平滚轮倾斜或旋转(一般没用)WM_RBUTTONDOWN :鼠标右键按下WM_RBUTTONUP:鼠标右键抬起 使用MSLLHOOKSTRUCT * msll = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);将lParam转换为MSLLHOOKSTRUCT结构体的指针,可通过这个结构体获取当前鼠标的坐标或者鼠标滚轮向前还是向后滚动的值。然后将获取到的鼠标事件映射为QMouseEvent、QWheelEvent事件,发送给当前程序使用;这里我使用的是QMouseEvent、QWheelEvent指针进行发送,由于QMouseEvent、QWheelEvent没有默认无参构造,所以在Linux下不支持使用信号发送QMouseEvent、QWheelEvent变量,所以只能使用指针;因为传递的是指针,所以在接收信号的槽函数里使用完后需要Delete,避免内存泄漏;简易这个信号只绑定一次,避免多个槽函数里使用同一个指针,一个槽函数释放了另外一个槽函数里出现野指针或者重复释放。不使用时需要使用UnhookWindowsHookEx()函数删除SetWindowsHookEx ()函数在挂钩链中安装的挂钩过程。

4、关键代码🍋

由于使用到了系统API,所以pro文件中需要链接系统库

win32 {LIBS+= -luser32 # 使用WindowsAPI需要链接库}

globalmouseevent.h

/******************************************************************************* @文件名mouseevent.h* @功能 全局鼠标事件监听类** @开发者mhf* @邮箱 1603291350@* @时间 /12/07* @备注*****************************************************************************/#ifndef MOUSEEVENT_H#define MOUSEEVENT_H#include <QObject>class QMouseEvent;class QWheelEvent;/*** 全局鼠标事件单例信号类*/class GlobalMouseEvent : public QObject{Q_OBJECTpublic:static GlobalMouseEvent* getInstance(){static GlobalMouseEvent mouseEvent;return &mouseEvent;}static bool installMouseEvent();// 安装全局鼠标事件监听器static bool removeMouseEvent(); // 卸载全局鼠标事件监听器signals:/*** @brief 由于传递的是指针,为了保证不会出现内存泄露,需要在槽函数中delete。* 建议此信号只绑定一次,因为如果绑定多次可能会出现一个槽函数里把信号delete了,另外一个槽函数还在使用,出现野指针,或者多个槽函数多次delete*/void mouseEvent(QMouseEvent* event);void wheelEvent(QWheelEvent* event);private:GlobalMouseEvent(){}};#endif // MOUSEEVENT_H

globalmouseevent_win.cpp

#include "globalmouseevent.h"#if defined(Q_OS_WIN)#include <QDebug>#include <QCursor>#include <QMouseEvent>#include "Windows.h"static HHOOK g_hook = nullptr;/*** @brief 处理鼠标事件的回调函数,由于这不是一个成员函数,所以需要通过中间单例类mouseEvent将鼠标信号传递出来* 具体内容看/zh-cn/previous-versions/windows/desktop/legacy/ms644986(v=vs.85)* @param nCode挂钩过程用于确定如何处理消息的代码。如果nCode小于零,则挂钩过程必须将消息传递给 CallNextHookEx 函数而不进行进一步处理,并且应返回CallNextHookEx返回的值* @param wParam 信号类型:WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVE、WM_MOUSEWHEEL、WM_MOUSEHWHEEL、WM_RBUTTONDOWN 或WM_RBUTTONUP(鼠标中键点击和拓展按还没找到怎么弄)。* @param lParam MSLLHOOKSTRUCT结构体指针* @return*/LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam){QPoint point = QCursor::pos(); // 获取鼠标当前位置switch (wParam){case WM_LBUTTONDOWN: // 鼠标左键按下emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonPress, point, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));break;case WM_MOUSEMOVE:// 鼠标移动emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseMove, point, Qt::NoButton, Qt::NoButton, Qt::NoModifier));break;case WM_RBUTTONDOWN: // 鼠标右键按下emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier));break;case WM_RBUTTONUP:// 鼠标右键抬起emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonRelease, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier));break;case WM_LBUTTONUP:// 鼠标左键抬起emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonRelease, point, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));break;case WM_MOUSEWHEEL: // 鼠标滚轮{MSLLHOOKSTRUCT * msll = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);// qDebug() << QString("坐标:(%1, %2)").arg(msll->pt.x).arg(msll->pt.y);// 获取鼠标坐标int delta = GET_WHEEL_DELTA_WPARAM(msll->mouseData); // 获取滚轮状态,向前:120,向后-120emit GlobalMouseEvent::getInstance()->wheelEvent(new QWheelEvent(point, delta, Qt::MiddleButton, Qt::NoModifier));break;}default:break;}return CallNextHookEx(nullptr, nCode, wParam, lParam); // 注意这一行一定不能少,否则会出大问题}/*** @brief 安装全局鼠标事件监听器* @return*/bool GlobalMouseEvent::installMouseEvent(){if(g_hook) return true;// 避免重复安装/*** WH_KEYBOARD_LL 为全局键盘钩子, WH_MOUSE_LL 为全局鼠标钩子* 详细说明看官方文档:/zh-cn/windows/win32/api/winuser/nf-winuser-setwindowshookexw*/g_hook = SetWindowsHookExW(WH_MOUSE_LL, LowLevelMouseProc, GetModuleHandleW(nullptr), 0);return g_hook;}/*** @brief 卸载全局鼠标事件监听器* @return*/bool GlobalMouseEvent::removeMouseEvent(){if(!g_hook) return true; // 避免重复卸载bool ret = UnhookWindowsHookEx(g_hook);if(ret){g_hook = nullptr;return true;}return false;}#endif

5、源代码🍌

giteegithub全局鼠标键盘事件监听器仓库github全局鼠标键盘事件监听器仓库giteeCSDN可以使用命令git clone /mahuifa/QtGlobalEvent.git直接下载仓库,然后引用到自己的程序中。

🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。