Qt USB设备拔插监测

Qt USB设备拔插监测

  • 环境
  • 目的
  • 方法
  • 例子
  • 疑问
    • 1. native Event 返回值
    • 2. 用 nativeEventFilter 处理消息

环境

Windows 系统
Qt5.4
c++语言

目的

让程序运行过程中能监测某一USB设备的拔插状态,当设备被拔出时进行相关处理。

方法

见 MSDN Device Messages 说明:

For each device event, the system broadcasts a WM_DEVICECHANGE message to all applications. In this message, the wParam parameter identifies the device event type and the lParam parameter is a pointer to event-specific data.

然而, WM_DEVICECHANGE 消息只会通知给TOP窗口,见 Detecting Media Insertion or Removal说明:

Windows sends all top-level windows a set of default WM_DEVICECHANGE messages when new devices or media (such as a CD or DVD) are added and become available, and when existing devices or media are removed.

但软件运行过程中TOP窗口并不固定,因此,选择一个软件开启到退出都会一直存在,不会析构的窗口注册消息来获取想要的消息通知。

注册消息用到函数是 RegisterDeviceNotification:

/*
winuser.h 头文件定义:如果是 unicode 编码,
则用 RegisterDeviceNotificationW,
其他则用 RegisterDeviceNotificationA
*/
HDEVNOTIFY RegisterDeviceNotificationW(
  HANDLE hRecipient, //指向窗口或服务的句柄
  LPVOID NotificationFilter, //接受设备通知句柄
  DWORD  Flags //说明 hRecipient 是用的窗口句柄还是设备服务句柄
);

NotificationFilter:
A pointer to a block of data that specifies the type of device for which notifications should be sent. This block always begins with the DEV_BROADCAST_HDR structure. The data following this header is dependent on the value of the dbch_devicetype member, which can be DBT_DEVTYP_DEVICEINTERFACE or DBT_DEVTYP_HANDLE.
 
DBT_DEVTYP_DEVICEINTERFACE:
Class of devices. This structure is a DEV_BROADCAST_DEVICEINTERFACE structure.

MSDN 例子中 NotificationFilter 参数用的是 DEV_BROADCAST_DEVICEINTERFACE 结构体,指明设备类型为设备接口类 DBT_DEVTYP_DEVICEINTERFACE 以及用来注册消息的 device interface class GUID。不同GUID说明见USB设备的插入检测

Flags:
DEVICE_NOTIFY_WINDOW_HANDLE: hRecipient is a windows handle
DEVICE_NOTIFY_SERVICE_HANDLE: hRecipient is a service status handle

例子

//注册消息需要添加头文件
#include 
#include 
//注册消息 
bool CLogin::RegisterHIVDeviceNotification()
{
    HDEVNOTIFY hDeviceNotify;
    /*
     *这里注册的设备是  Human Interface Devices (HID) 类
     *GUID_DEVINTERFACE_HID = {4D1E55B2-F16F-11CF-88CB-001111000030}
    */
    GUID  guid_hiv = {0x4D1E55B2, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30};
    DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
    HWND hWnd = (HWND)(this->winId()); //获取当前窗口句柄
    ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
    NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    NotificationFilter.dbcc_classguid = guid_hiv;
    hDeviceNotify = RegisterDeviceNotification (hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
    if (NULL == hDeviceNotify)
        return false;
    else
        return true; //注册消息成功
}

//处理接受到的消息
// nativeEvent 是重载的虚函数
bool CLogin::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    Q_UNUSED(eventType); //未用该参数
    Q_UNUSED(result); //未用该参数
    MSG *msg = reinterpret_cast<MSG*>(message);
    //消息类型是 设备改变 且为 设备拔出
    if (msg->message == WM_DEVICECHANGE && msg->wParam == DBT_DEVICEREMOVECOMPLETE)
    {
        emit SigDeviceRemove(); //发送信号处理
    }
    return false; 
}

疑问

1. native Event 返回值

返回 false 表示消息继续传递,开始在消息处理后返回 true ,结果界面为空白,没明白原因???
用事件过滤器时处理完消息返回true都没问题

2. 用 nativeEventFilter 处理消息

参考: Qt: usb热插拔检测(windows) 里介绍方法,用 nativeEventFilter 来处理消息,在主程序main.cpp中安装事件过滤器 installNativeEventFilter。

实现函数 nativeEventFilter 的类需要继承 QAbstractNativeEventFilter,之前用该方法没成功实现,用该方法时未注册消息,以后补充。

你可能感兴趣的:(QT,#,QT零散学习笔记)