当前位置: 首页 > news >正文

Qt开发:nativeEvent事件的使用

文章目录

    • 一、概述
    • 二、nativeEvent 的定义
    • 三、Windows 平台示例
    • 三、使用nativeEvent监测设备变化

一、概述

Qt 的 nativeEvent 是一个特殊的事件处理机制,允许开发者处理操作系统级别的原生事件。通常,Qt 通过 QEvent 机制来管理事件,但有时我们需要直接处理底层的原生事件,例如 Windows 消息(Windows API)、X11 事件(Linux)、macOS 事件等。

二、nativeEvent 的定义

nativeEvent 是 QCoreApplication 和 QApplication 提供的一个虚函数:

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
#else
    virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#endif

该函数在 Qt 事件循环中会被调用,用于拦截操作系统原生事件。
参数解析:

  • eventType:事件类型,例如 Windows 下通常是 “windows_generic_MSG” 或"windows_dispatcher_MSG"。
  • message:指向操作系统事件的指针。例如,在 Windows 下,它是 MSG*。
  • result:用于返回处理结果(可选)。

返回值:

  • true:表示事件已被处理,不需要传递给 Qt 继续处理。
  • false:表示事件未被处理,Qt 仍然会继续处理它。

三、Windows 平台示例

在 Windows 上,message 其实是 MSG*,可以用来拦截特定的 Windows 消息,比如 WM_HOTKEY(全局热键)。

#include <QApplication>
#include <QDebug>
#include <QWidget>
#include <windows.h>
class MyWidget : public QWidget {
protected:
    bool nativeEvent(const QByteArray &eventType, void *message, long * result) override {
        if (eventType == "windows_generic_MSG") {
            MSG *msg = static_cast<MSG *>(message);
            if (msg->message == WM_HOTKEY) {
                qDebug() << "Hotkey Pressed!";
                return true;  // 表示事件已处理
            }
        }
        return QWidget::nativeEvent(eventType, message, result);
    }

public:
    MyWidget() {
        // 注册全局热键:Ctrl + Alt + H
        RegisterHotKey((HWND)winId(), 1, MOD_CONTROL | MOD_ALT, 'H');
    }

    ~MyWidget() {
        UnregisterHotKey((HWND)winId(), 1);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget w;
    w.show();
    return app.exec();
}

输出结果:
在这里插入图片描述

三、使用nativeEvent监测设备变化

1. WM_DEVICECHANGE 的基本定义
WM_DEVICECHANGE 是 Windows 操作系统提供的一个系统消息(System Message),用于通知应用程序系统中设备(如 USB 设备、存储设备、网卡等)发生了变化。例如,当插入或移除 USB 设备时,系统会发送 WM_DEVICECHANGE 消息。

在 Windows.h 头文件中,WM_DEVICECHANGE 的定义如下:

#define WM_DEVICECHANGE 0x0219

当某个设备发生变化时,Windows 会向所有顶级窗口(包括 Qt 窗口)发送 WM_DEVICECHANGE 消息。该消息的 wParam 参数表示具体的设备变化类型,常见的值如下:
在这里插入图片描述
其中,DBT_DEVICEARRIVAL 和 DBT_DEVICEREMOVECOMPLETE 是最常见的,用于检测 USB 设备插拔。

2. Qt 中拦截 WM_DEVICECHANGE 事件

#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <windows.h>
#include <dbt.h>

class DeviceMonitorWidget : public QWidget {
protected:
    bool nativeEvent(const QByteArray &eventType, void *message, long *result) override {
        if (eventType == "windows_generic_MSG") {
            MSG *msg = reinterpret_cast<MSG*>(message);
            if (msg->message == WM_DEVICECHANGE) {
                PDEV_BROADCAST_HDR pHdr = reinterpret_cast<PDEV_BROADCAST_HDR>(msg->lParam);
                PDEV_BROADCAST_VOLUME pVolume = reinterpret_cast<PDEV_BROADCAST_VOLUME>(pHdr);
                if (msg->wParam == DBT_DEVICEARRIVAL) {
                    if (pHdr->dbch_devicetype == DBT_DEVTYP_VOLUME) {
                        if (pVolume->dbcv_flags == 0) {
                            qDebug() << "U Disk inserted";
                            //获取当前系统的盘符
                            QFileInfoList fileList = QDir::drives();
                            QString strPath;
                            for (int i = 0; i < fileList.count(); i++) {
                                strPath = fileList[i].filePath();
                                qDebug() << "strPath:" << strPath;
                                
                                const wchar_t *w_usb = reinterpret_cast<const wchar_t*>(strPath.utf16());
                                UINT iRet = GetDriveType(w_usb);
                                if (iRet == DRIVE_REMOVABLE) {
                                    qDebug() << "it's a U Disk," << "Name:" << strPath;
                                }
                            }
                        }
                    }       
                } else if (msg->wParam == DBT_DEVICEREMOVECOMPLETE) {
                    if (pHdr->dbch_devicetype == DBT_DEVTYP_VOLUME) {
                        if (pVolume->dbcv_flags == 0) {
                            qDebug() << "Pull out the U Disk";
                        }
                    }
                }
            }
        }
        return QWidget::nativeEvent(eventType, message, result);
    }

public:
    DeviceMonitorWidget() {
        setWindowTitle("设备监视器");
        resize(300, 200);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    DeviceMonitorWidget w;
    w.show();
    return app.exec();
}

相关文章:

  • STM32-I2C通信外设
  • 2025最新群智能优化算法:海市蜃楼搜索优化(Mirage Search Optimization, MSO)算法求解23个经典函数测试集,MATLAB
  • TinyWebServer项目笔记——01 线程同步机制封装类
  • 模型微调——模型性能提升方法及注意事项(自用)
  • 【微知】Centos如何迁移到Anolis系统的失败记录?(yum -y install centos2anolis、centos2anolis.py)
  • 正版Windows10/11系统盘制作详细教程
  • 基于单片机及传感器的机器人设计与实现
  • doris:SAP HANA
  • 微信小程序将markdown内容转为pdf并下载
  • VBA 列方向合并单元格,左侧范围大于右侧范围
  • python: DDD+ORM using oracle 21c
  • Ollama本地部署大模型(Mac M1 )
  • 生物电阻抗技术:精准洞察人体营养的“智能窗口”
  • 安固软件上网行为管理软件:提升企业效率与安全的双重保障
  • MongoDB用户管理和复制组
  • 基于multisim的自动干手器设计与仿真
  • GitHub神秘组织3小时极速复刻Manus
  • 【C++多线程】std::async和std::future
  • 《从零构建企业级容器镜像生态:Harbor与Registry双星架构实战手记》
  • 【redis】布隆过滤器的Java实现
  • 建造师官网/seo技术分享免费咨询
  • 韩韩良品只做性价比网站下载/职业培训学校加盟合作
  • 营销型网站制作公司/中文网站排名
  • 宝安区做网站/合肥网络推广服务
  • 泰安华航网络有限公司/优化模型数学建模
  • php如何自学做网站/企业推广软文