關於windows熱插拔檢測的個人理解(使用Qt開發)
阿新 • • 發佈:2018-12-09
在Qt中每一個視窗類(widget)都有一個處理windows訊息的函式,當windows出現熱插拔事件的時候,會向每個視窗傳送相應的WM_訊息,在Qt下,最終將調到natevieEvent函式;下面以QWidget為例:
virtual bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result);
一旦發生熱插拔事件,QWidget的nativeEvent函式將被呼叫,於是我們可以重新實現這個函式;
//Qt開發 virtual bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result) { //在這裡做你想要的操作 //其中eventType表明了此次訊息的型別,message儲存著具體是什麼資訊,result是個傳出變數; //eventType在windows作業系統下是"windows_generic_MSG"字串,可以檢視Qt的文件知道 //message表明這個訊號附帶哪些資訊,在熱插拔事件中是WM_DEVICECHANGE型別,具體windows定義了哪些,可以檢視“Dbt.h”檔案 // if(eventType == QByteArray("windows_generic_MSG")) { //MSG是winApi定義的結構體,具體定義如下: /* * typedef struct tagMSG { * HWND hwnd; * UINT message; //訊息型別,熱插拔是WM_DEVICECHANGE * WPARAM wParam; //對訊息的進一步描述 * LPARAM lParam; //指向一個結構體,結構中有好多訊息 * DWORD time; //產生時間 * POINT pt; //滑鼠座標 * } MSG; */ MSG *pMsg = reinterpret_cast<MSG*>(message); if(pMsg->message == WM_DEVICECHANGE) { switch(pMsg->wParam) { //裝置連上 case DBT_DEVICEARRIVAL: doSomething(); break; //裝置斷開 case DBT_DEVICEREMOVECOMPLETE: doSomething(); break; //其他的訊息可以檢視“Dbt.h”檔案 } } } return false; }
經過以上步驟,程式能夠捕捉到相應的訊息,但無法區分是由哪個裝置發出的;
然而很不巧的是,我也不懂,只知道一點,應該和LParam有關;
----------------------------------------------手動分割-----------------------------------------------------
下面的內容不作任何保障:
我查到的是:
第一步:先註冊訊息;
第二步:不知道!
先來說第一步:
首先你要知道有這麼一個 DEV_BOARDCAST_DEVICEINTERFACE結構體,從名稱上看,這就是一個和裝置廣播介面
//定義如下,別問為什麼多了"_A", //其實還有一個"_DEV_BROADCAST_DEVICEINTERFACE_W" //這個和應該是和平臺相關的 //所以不管,至少長得一樣 typedef struct _DEV_BROADCAST_DEVICEINTERFACE_A { DWORD dbcc_size; //大小 DWORD dbcc_devicetype;//裝置型別 DWORD dbcc_reserved; //保留字,忽略即可 GUID dbcc_classguid; //裝置類guid char dbcc_name[1]; //名字,不知道怎麼用 } DEV_BROADCAST_DEVICEINTERFACE_A, *PDEV_BROADCAST_DEVICEINTERFACE_A;
//關於DEV_BOARDCAST_DEVICEINTERFACE的一個例子 DEV_BOARDCAST_DEVICEINTERFACE devInterface; //為各個成員賦值 devInterface.dbcc_size = sizeof(DEV_BOARDCAST_DEVICEINTERFACE); devInterface.dbcc_devicetype = DBT_DEVTYPE_DEVICEINTERFACE;//其他的型別檢視“Dbt.h”檔案, devInterface.dbcc_classguid = GUID_DEVCLASS_USB;//其他型別檢視“devguid.h”檔案
其中的“dbcc_devicetype”的值將直接影響到“nativeEvent”中“MSG”結構體中的“meaasge”結構體中的“LParam”成員;
當,一個DEV_BOARDCAST_DEVICEINTERFACE結構體定義好了之後,就可以註冊了
//使用如下函式註冊
//
/*
* 函式定義,別問為什麼是“W”
* HDEVNOTIFY RegisterDeviceNotificationW(
* HANDLE hRecipient,
* LPVOID NotificationFilter,
* DWORD Flags //檢視"winuser.h"
* );
*/
//Qt開發環境下
RegisterDeviceNotification(HANDLE(this->winId()), &devInterface, DEVICE_NOTIFY_WINDOW_HANDLE);
至此註冊完畢,最後能知道是GUID_DEVCLASS_USB這種型別裝置產生的訊號(訊息);
那麼怎麼知道是哪個裝置產生的呢(前面說的是哪種),就要看“LParam”了;