引言:在日常串口开发中,串口热插拔的实时检测可以大大提高我们的使用体验,不至于在要添加串口时重启一遍软件,这样显得很不专业。
调用注册事件的类需要继承 QAbstractNativeEventFilter ,这是一个纯虚函数类
重写函数:
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) = 0:
第一步(注册监测设备)
-
注册事件要小心的点在于注册事件不能写在函数外,所以需要写一个初始化注册函数 registerDevice()调用,在UI初始化时调用即可
接下来就直接上代码:
void MainWindow::registerDevice(){
static const GUID GUID_DEVINTERFACE_LIST[] =
{
// GUID_DEVINTERFACE_USB_DEVICE
{ 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }, //USB设备的GUID
// GUID_DEVINTERFACE_DISK
{ 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } },
// GUID_DEVINTERFACE_HID,
{ 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },
// GUID_NDIS_LAN_CLASS
{ 0xad498944, 0x762f, 0x11d0, { 0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3, 0x35, 0x8c } },
// GUID_DEVINTERFACE_COMPORT
{ 0x86e0d1e0, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73 } },
// GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
{ 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },
// GUID_DEVINTERFACE_PARALLEL
{ 0x97F76EF0, 0xF883, 0x11D0, { 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x5C } },
// GUID_DEVINTERFACE_PARCLASS
{ 0x811FC6A5, 0xF728, 0x11D0, { 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75, 0x3E, 0xD1 } },
};
//注册插拔事件
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)this->winId(), &NotifacationFiler, DEVICE_NOTIFY_WINDOW_HANDLE);
if (!hDevNotify) {
qCritical() << QStringLiteral("注册失败!");
}else{
qDebug()<<"注册成功";
}
}
}
第二步(重写消息过滤函数)
bool Moveing_target::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
Q_UNUSED(eventType);
MSG* msg = reinterpret_cast<MSG*>(message);
int msgType = msg->message;
if(msgType == WM_DEVICECHANGE)
{
qDebug() << "Recv Event " ;
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)msg->lParam;
switch(msg->wParam)
{
case DBT_DEVICETYPESPECIFIC:
{
qDebug() << "DBT_DEVICETYPESPECIFIC " ;
break;
}
case DBT_DEVICEARRIVAL:
if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
if (lpdbv -> dbcv_flags == 0)
{
// 插入U盘,此处可以做你想做的事
// lpdbv->dbcv_unitmask 即盘符标志位,1bit,0为A,1为B,10为C,11为D…以此类推
QString USBDisk = QString(this->FirstDriveFromMask(lpdbv->dbcv_unitmask));
qDebug() << "USB_Arrived and The USBDisk is: "<<USBDisk ;
emit signals_Usb_Stick_Insertion(USBDisk);
}
}
qDebug() << "DBT_DEVICEARRIVAL" ;
break;
case DBT_DEVICEREMOVECOMPLETE:
if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
if (lpdbv -> dbcv_flags == 0)
{
qDebug() << "USB_delete";
}
}
qDebug() << "DBT_DEVICEREMOVECOMPLETE" ;
break;
}
}
return false;
}
char Moveing_target::FirstDriveFromMask(ULONG unitmask)
{
char i;
for (i = 0; i < 26; ++i)
{
if (unitmask & 0x1)
break;
unitmask = unitmask >> 1;
}
return (i + 'A');
}
然后在把继承的类插入QApplication对象里安装此过滤器即可
a.installNativeEventFilter(&t);