前言
在项目中,遇到一个需求:需要动态监测U盘插入,自动读取U盘文件并打开。为了实现这个功能,我们可以使用RegisterDeviceNotification注册设备事件的通知,
然后在程序中处理WM_DEVICECHANGE消息来实现
步骤
RegisterDeviceNotification注册设备事件的通知
在QWidget中重新实现它的nativeEvent函数来接收处理WM_DEVICECHANGE消息
具体代码
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(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消息,但我们业务处理只需要进行一次即可,因此通过该标志位进行限定