QT监测HID设备的拔插

需要包含的头文件

#include <MessageDispatcherApi.h>
#include <QWidget>
#include <Windows.h>
#include <WinUser.h>
#include <dbt.h>
#include <QApplication>
#include <QDebug>
#include <devguid.h>
#include <SetupAPI.h>
#include <InitGuid.h>

涉及到的类:

tagMSG / MSG

      MSG是Windows程序中的结构体,成员结构如下:

typedef struct tagMSG
{
  HWND hwnd; // 消息指向的窗口句柄
  UINT message; //消息名称
  WPARAM wParam; //消息的附加信息
  LPARAM lParam; //消息的附加信息
  DWORD time;  //创建时间
  POINT pt; //创建时的鼠标位置
} MSG;


hwnd  消息所属的窗口

message 消息的标识符

             例如 WM_DEVICECHANGE(设备拔插变化)、WM_LBUTTONDOWN(鼠标左键按下)、WM_KEYDOWN(键盘按下)等,WM是Windows Message的缩写

wparam 32位整数,表示设备的状态变化

     —— DBT_DEVICEARRIVAL 设备已经插入且可以使用了

     —— DBT_DEVICEREMOVECOMPLETE 设备已经成功移出

lparam 32位整数,指向DEV—BROADCAST_HDR结构的指针

 

QT5中使用nativeEvent(const QByteArray &eventType, void *message, long *resutl)代替原来的winEvent函数作消息响应的处理

普通USB的拔插可以通过检测DBT_DEVTYP_PORT以及DBT_DEVNODES_CHANGED的变化来实现,但是我这里需要监测的是单片机上的识别为HID的USB设备,且只有这个特定的设备拔插时才发生变化,故需要对设备进行通知注册

不同类型的设备有特定的唯一的Class GUID,利用这个GUID可以向窗体注册设备通知,我的是HID设备,故应该使用GUID_DEVINTERFACE_HID,使用该GUID要包含“initGUID”头文件

  //给设备注册通知
    DEV_BROADCAST_DEVICEINTERFACE Notificationfilter;
    ZeroMemory(&Notificationfilter,sizeof(DEV_BROADCAST_DEVICEINTERFACE));
    Notificationfilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    Notificationfilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;

    //Notificationfilter.dbcc_classguid ={0x745a17a0,0x74d3,0x11d0,{0xb6,0xfe,0x00,0xa0,0xc9,0x0f,0x57,0xda}};
    Notificationfilter.dbcc_classguid = {0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 }};

    hDevNotify = RegisterDeviceNotificationW((HANDLE)this->winId(),&Notificationfilter,DEVICE_NOTIFY_WINDOW_HANDLE);
    if(!hDevNotify)
    {
       qDebug() << "注册失败" << endl;
    }

 

注册完毕后检测WM_DEVICECHANGE,进行相应的处理

bool Form::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    Q_UNUSED(eventType);
    Q_UNUSED(result);

    MSG* msg = reinterpret_cast<MSG*>(message);
    int msgType = msg->message;

    if(msgType == WM_DEVICECHANGE)
    {
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)msg->lParam;
        switch(msg->wParam)
        {
        case DBT_DEVICEARRIVAL:     //有设备插入且可以使用

            qDebug() << "DBT_DEVICEARRIVAL";

            if(lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
              {
                  qDebug() << "DBT_DEVTYP_DEVICEINTERFACE";
                  ui->label->setText(tr("Device is connecting!"));
                  ui->label->setStyleSheet("font:bold;font-size:20px;color:red;background-color:black");
                  update = 1;
              }
              break;
        case DBT_DEVICEREMOVECOMPLETE:
           
            if(lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
            {
                ui->label->setText(tr("NO Device connecting!"));
                ui->label->setStyleSheet("font:bold;font-size:20px;color:white;background-color:black");
                update = 0;
            }
            qDebug() << "DBT_DEVICEREMOVECOMPLETE";
            break;
         }
     }
}

 

特别地:

    当message的类型是WM_DEVICECHANGE时,其lparam是一个指向_DEV_BROADCAST_HDR结构体的指针,结构体内容如下:

typedef struct _DEV_BROADCAST_HDR

 {

  DWORD dbch_size;     

  DWORD dbch_devicetype;

  DWORD dbch_reserved;

} DEV_BROADCAST_HDR, *PDEV_BROADCAST_HDR;

而当dbch_devicetype是DBT_DEVTYP_VOLUME,即逻辑驱动时,lparam实际指向的是其结构体实例_DEV_BROADCAST_VOLUME,结构体内容如下:

typedef struct _DEV_BROADCAST_VOLUME {

     DWORD dbcv_size;   //结构体实例的字节数

    DWORD dbcv_devicetype;   //驱动器类型

     DWORD dbcv_reserved;   

     DWORD dbcv_unitmask;   //当前改变的驱动器掩码(驱动器号)

     WORD dbcv_flags;   //驱动器的类别  1- 光盘驱动  2 - 网路驱动  0 - 硬盘、U盘

 } DEV_BROADCAST_VOLUME, *PDEV_BROADCAST_VOLUME;

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值