admin管理员组

文章数量:1654725

目录

    • 1 背景
    • 2 Qt处理Windows消息
    • 3 实现
    • 4 运行效果

1 背景

最近为自己使用的资源管理实现U盘动态检测插拔功能,通过在网上查资料,发现在Windows下,当插拔磁盘时Windows会给应用发送广播消息WM_DEVICECHANGE通知各应用设备发生变化了,应用可以根据该消息来检测U盘动态插拔。下面讲述在Qt下如何检测WM_DEVICECHANGE消息,并检测U盘插拔。

2 Qt处理Windows消息

Windows消息是发送给窗口的,在Qt下窗口就是QWidget,QWidget有一个protected类型虚函数nativeEvent来处理平台本地消息,函数原型如下:

[virtual protected] bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)

在Windows平台下各参数意义如下:

eventType : "windows_generic_MSG"
message:    MSG *
result:     LRESULT

可以重载该函数来处理WM_DEVICECHANGE消息。

3 实现

从QWidget派生一个类型Widget,如下所示:

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
protected:
    bool nativeEvent(const QByteArray &eventType,
                     void *message,
                     long *result) override;
};

实现虚函数nativeEvent

bool Widget::nativeEvent(const QByteArray &eventType,
                 void *message,
                 long *result)
{
    Q_UNUSED(eventType)
    MSG* msg = (MSG*)message;
    if(msg->message == WM_DEVICECHANGE)
    {
        if(msg->wParam == DBT_DEVICEARRIVAL)
        {
            PDEV_BROADCAST_HDR devHdr = (PDEV_BROADCAST_HDR)msg->lParam;
            if(devHdr->dbch_devicetype == DBT_DEVTYP_VOLUME)
            {
                //U盘插入, 更新驱动器列表
            }
            *result = 0;
        }
        else if(msg->wParam == DBT_DEVICEREMOVECOMPLETE)
        {
            PDEV_BROADCAST_HDR devHdr = (PDEV_BROADCAST_HDR)msg->lParam;
            if(devHdr->dbch_devicetype == DBT_DEVTYP_VOLUME)
            {
                //U盘拔出, 更新驱动器列表
            }
            *result = 0;
        }
    }
    return false;//返回false表明该消息接着向下传递,以便其它应用处理该消息。
}

如上所示将参数message转换为MSG*类型msg,通过检测msg的成员message,wParam和lParam类型来判断U盘插拔。

  • msg成员message是否是WM_DEVICECHANGE类型, 如果是则检测msg的wParam参数。
  • 如果wParam是DBT_DEVICEARRIVAL表明设备插入,是DBT_DEVICEREMOVECOMPLETE表明设备拔出。
  • 如何检测设备是U盘而不是鼠标/键盘以及其它设备呢?这就需要通过msg参数lParam判断了。如果lParam类型为DBT_DEVTYP_VOLUME就表明设备是U盘。

4 运行效果

本文标签: 插拔动态QT