我是靠谱客的博主 乐观板凳,最近开发中收集的这篇文章主要介绍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;

最后

以上就是乐观板凳为你收集整理的QT监测HID设备的拔插的全部内容,希望文章能够帮你解决QT监测HID设备的拔插所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部