QT January 15, 2020

【QT】动态监测U盘插拔

Words count 5.8k Reading time 5 mins. Read count 0

前言

在项目中,遇到一个需求:需要动态监测U盘插入,自动读取U盘文件并打开。为了实现这个功能,我们可以使用RegisterDeviceNotification注册设备事件的通知,
然后在程序中处理WM_DEVICECHANGE消息来实现

步骤

  1. RegisterDeviceNotification注册设备事件的通知
  2. 在QWidget中重新实现它的nativeEvent函数来接收处理WM_DEVICECHANGE消息

具体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
bool GlobalUtil::registerDevNitification(QWidget *widget)
{
static const GUID GUID_DEVINTERFACE_LIST[] =
{
{ 0xA5DCBF10, 0x6530, 0x11D2,{ 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },
{ 0x53f56307, 0xb6bf, 0x11d0,{ 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } },
{ 0x4D1E55B2, 0xF16F, 0x11CF,{ 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },
{ 0xad498944, 0x762f, 0x11d0,{ 0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3, 0x35, 0x8c } }
};
HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotifacationFiler;
ZeroMemory(&NotifacationFiler, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
NotifacationFiler.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotifacationFiler.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;

for (int i = 0; i < sizeof(GUID_DEVINTERFACE_LIST) / sizeof(GUID); i++)
{
NotifacationFiler.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];

hDevNotify = RegisterDeviceNotification((HANDLE)widget->winId(), &NotifacationFiler, DEVICE_NOTIFY_WINDOW_HANDLE);
if (!hDevNotify)
{
return false;
}
}
return true;
}

// 将需要处理WM_DEVICECHANGE消息的widget进行注册
GlobalUtil::registerDevNitification(widget);
// 在widget中重新实现nativeEvent函数
bool LoginWindow::nativeEvent(const QByteArray & eventType, void * message, long*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:
if (lpdb->dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE)
{
m_callback++;
if (m_callback % 2 == 0)
{
// 具体的业务处理
}
}
break;
}
}
return false;
}

其他补充

看到上边,采用了一个m_callback标志位进行限制,这是因为U盘插入后,会连续发送两次WM_DEVICECHANGE消息,但我们业务处理只需要进行一次即可,因此通过该1标志位进行限定

0%