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

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

更多精彩内容
👉个人内容分类汇总 👈
👉Qt自定义模块、工具👈

1、概述🍈

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

2、实现效果🍉

在这里插入图片描述

3、实现方式🍊

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

4、关键代码🍋

  • 由于使用到了系统API,所以pro文件中需要链接系统库
win32 {
LIBS+= -luser32    # 使用WindowsAPI需要链接库
}
  • globalmouseevent.h
/******************************************************************************
 * @文件名     mouseevent.h
 * @功能       全局鼠标事件监听类
 *
 * @开发者     mhf
 * @邮箱       1603291350@qq.com
 * @时间       2022/12/07
 * @备注
 *****************************************************************************/
#ifndef MOUSEEVENT_H
#define MOUSEEVENT_H

#include <QObject>

class QMouseEvent;
class QWheelEvent;

/**
 *  全局鼠标事件单例信号类
 */
class GlobalMouseEvent : public QObject
{
    Q_OBJECT
public:
    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将鼠标信号传递出来
 *                  具体内容看https://learn.microsoft.com/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,向后-120
        emit 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 为全局鼠标钩子
     * 详细说明看官方文档:https://learn.microsoft.com/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、源代码🍌

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

### 回答1: qt-unified-windows-x86-4.0.1-online.exe 是一个 Qt 软件开发工具的安装程序,该工具可用于开发跨平台应用程序。 Qt 是一个跨平台 C++ 库,它能够使软件开发更加快速而且易于使用。Qt 库包含了很多模块,包括 GUI、网络、数据库、XML 等等。Qt 软件开发工具是一个可以快速开发可运行于多个操作系统(如 Windows、OS X、Linux 和 Android)的跨平台应用程序的工具。 qt-unified-windows-x86-4.0.1-online.exe 是一个在线安装程序,它需要连接到 Qt 公司的服务器来下载和安装软件。安装过程中可以选择使用该工具以及可能需要的模块和对应的版本(如 Qt Creator、Qt Designer、Qt WebEngine 等等)。注意:安装程序需要联网。 总之,Qt 软件开发工具是一个为了方便开发者快速创建跨平台应用程序而设计的工具。qt-unified-windows-x86-4.0.1-online.exe 是该工具的一个在线安装程序,方便用户自定义安装过程。 ### 回答2: qt-unified-windows-x86-4.0.1-online.exe是一个Qt跨平台开发工具的安装文件。它是一个在线安装程序,主要用于Windows操作系统中32位的x86架构。Qt是一个功能强大的开发工具包,它具有GUI开发工具、网络模块、数据库支持等功能,能够帮助开发者快速地构建高质量、可扩展性的应用程序。Qt的跨平台开发特点,使得开发者可以同时在多个平台上开发,只需一次编码,即可运行于不同的操作系统上。qt-unified-windows-x86-4.0.1-online.exe通过网络安装,能够自动下载和安装必要的组件和工具,从而降低了Qt工具包的安装难度和复杂度。此外,Qt还提供了C++语言的编程接口和QML语言的脚本编写方式,使得开发者能够根据自己的需要选择不同的编程方式来进行应用程序的开发。因此,qt-unified-windows-x86-4.0.1-online.exe是一个非常有用的工具,适合想要开发跨平台应用程序的开发者使用。 ### 回答3: qt-unified-windows-x86-4.0.1-online.exe是一款QT开发环境的安装程序,适用于Windows x86系统。使用这个程序可以帮助开发者在Windows系统上快速安装QT开发环境。QT是一款跨平台开发框架,用于开发桌面应用、移动应用和嵌入式应用等。QT开发框架支持C++编程语言,并提供了一系列丰富的库,开发者可以使用这些库来构建自己的应用程序。 qt-unified-windows-x86-4.0.1-online.exe是一款在线安装程序,它需要联网下载QT开发环境的相关组件。安装过程中,开发者可以选择需要安装的组件,例如QT Creator、QT Designer等等。安装完成后,开发者就可以开始使用QT开发框架来开发自己的应用程序了。 总之,QT开发框架是一款十分强大的开发工具,它可以帮助开发者快速构建跨平台的应用程序。qt-unified-windows-x86-4.0.1-online.exe则是一款方便快捷的安装程序,可以帮助开发者在Windows x86系统上快速安装QT开发环境。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mahuifa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值