首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 偵測 USB 裝置插拔:WM_DEVICECHANGE 訊息處理

     編輯:VC 教學

核心機制

Windows 透過 WM_DEVICECHANGE 視窗訊息通知應用程式裝置到達/移除。wParam 為事件類型,lParam 指向 DEV_BROADCAST_HDR 結構,可轉型為 DEV_BROADCAST_VOLUME 判斷磁碟機類型。

訊息處理範本

BOOL CMyDlg::OnDeviceChange(UINT nEventType, DWORD dwData)
{
    PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)dwData;
    if (!pHdr) return TRUE;

    switch (nEventType) {
    case DBT_DEVICEARRIVAL:      // 裝置到達
        if (pHdr->dbch_devicetype == DBT_DEVTYP_VOLUME) {
            PDEV_BROADCAST_VOLUME pVol = (PDEV_BROADCAST_VOLUME)pHdr;
            // pVol->dbcv_unitmask 位圖:bit 0=A:, bit 1=B: ...
            for (int i = 0; i < 26; ++i) {
                if (pVol->dbcv_unitmask & (1 << i)) {
                    TCHAR szDrive[4] = { _T('A') + i, _T(':'), _T('\\'), 0 };
                    if (GetDriveType(szDrive) == DRIVE_REMOVABLE) {
                        // 偵測到 USB 磁碟/隨身碟插入
                        OnUsbInserted(szDrive);
                    }
                }
            }
        }
        break;

    case DBT_DEVICEREMOVECOMPLETE: // 裝置移除完成
        if (pHdr->dbch_devicetype == DBT_DEVTYP_VOLUME) {
            PDEV_BROADCAST_VOLUME pVol = (PDEV_BROADCAST_VOLUME)pHdr;
            // 同理解析 unitmask,判斷移除的磁碟機
            OnUsbRemoved(pVol->dbcv_unitmask);
        }
        break;

    case DBT_DEVNODES_CHANGED:   // 裝置拓撲變更 (通用)
        RefreshDeviceList();
        break;
    }
    return TRUE;
}

關鍵結構體

typedef struct _DEV_BROADCAST_VOLUME {
    DWORD dbcv_size;        // 結構大小
    DWORD dbcv_devicetype;  // DBT_DEVTYP_VOLUME (0x00000002)
    DWORD dbcv_reserved;
    DWORD dbcv_unitmask;    // 位圖,對應磁碟機代號
    WORD  dbcv_flags;       // DBTF_MEDIA (媒體變更) / DBTF_NET (網路磁碟)
} DEV_BROADCAST_VOLUME, *PDEV_BROADCAST_VOLUME;

註冊介面裝置通知 (可選)

若需偵測非磁碟類 USB 裝置 (如印表機、HID),需呼叫 RegisterDeviceNotification 註冊 GUID 介面類別:

GUID InterfaceClassGuid = GUID_DEVINTERFACE_USB_DEVICE; // 或特定類別 GUID
DEV_BROADCAST_DEVICEINTERFACE filter = {0};
filter.dbcc_size = sizeof(filter);
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
filter.dbcc_classguid = InterfaceClassGuid;
HDEVNOTIFY hNotify = RegisterDeviceNotification(m_hWnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE);
// 視窗銷毀時 UnregisterDeviceNotification(hNotify);

常見坑點

  1. 服務程式:服務無視窗句柄,需用 RegisterDeviceNotification 搭配 SERVICE_CONTROL_DEVICEEVENT。
  2. 權限:Vista+ 非管理員執行也可收到 WM_DEVICECHANGE,但部分裝置資訊受限。
  3. 虛擬機/遠端桌面:虛擬 USB 重導向可能產生重複或缺失事件,需去抖動處理。
  4. unitmask 為 0:某些事件 (如媒體變更) 不帶磁碟機位圖,需結合 GetLogicalDrives 比對前後差異。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved