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

VC++ 偵測 USB 隨插即用裝置插拔:WM_DEVICECHANGE 訊息完整處理範例

     編輯:VC 教學

應用程式常需即時感應 U 盤、移動硬碟等可移除裝置的插入與拔出。Windows 透過 WM_DEVICECHANGE 訊息通知應用層,配合 DEV_BROADCAST_VOLUME 結構即可識別磁碟機代號並執行對應邏輯 (如自動備份、病毒掃描、UI 更新)。

核心處理架構

// 在 CWnd 衍生類中覆寫 OnDeviceChange
BOOL CMyWnd::OnDeviceChange(UINT nEventType, DWORD dwData)
{
    PDEV_BROADCAST_HDR hdr = (PDEV_BROADCAST_HDR)dwData;
    if (!hdr) return TRUE;

    // 僅處理磁碟機裝置 (DBT_DEVTYP_VOLUME)
    if (hdr->dbch_devicetype != DBT_DEVTYP_VOLUME) return TRUE;

    PDEV_BROADCAST_VOLUME vol = (PDEV_BROADCAST_VOLUME)hdr;
    DWORD unitMask = vol->dbcv_unitmask; // 位遮罩,bit 0=A:, bit 1=B: ...
    int driveLetter = -1;

    // 找到第一個置位的 bit
    for (int i = 0; i < 26; ++i) {
        if (unitMask & (1 << i)) { driveLetter = i; break; }
    }
    if (driveLetter == -1) return TRUE;

    CString driveRoot;
    driveRoot.Format(_T("%c:\\"), _T('A') + driveLetter);

    switch (nEventType) {
    case DBT_DEVICEARRIVAL: // 裝置插入
        if (GetDriveType(driveRoot) == DRIVE_REMOVABLE) {
            // 確認是可移除磁碟 (U 盤等)
            OnUsbInserted(driveRoot); // 自訂處理:掃描、備份、提示...
        }
        break;

    case DBT_DEVICEREMOVECOMPLETE: // 裝置移除完成
        if (GetDriveType(driveRoot) == DRIVE_REMOVABLE) {
            OnUsbRemoved(driveRoot);  // 自訂處理:清理暫存、UI 更新...
        }
        break;

    case DBT_DEVNODES_CHANGED:
        // 設備拓撲變更,可選處理
        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;

實作要點

  1. 訊息映射: ON_WM_DEVICECHANGE() (MFC 自動映射虛擬函數 OnDeviceChange)。
  2. 多磁碟機同時變更: dbcv_unitmask 可能有多個 bit 置位,實際專案應迴圈處理每個磁碟機。
  3. 媒體變更 vs 裝置插拔: dbcv_flags & DBTF_MEDIA 表示磁碟機已存在但媒體更換 (如換光碟);DBT_DEVICEARRIVAL/REMOVECOMPLETE 針對裝置本身。
  4. 權限: Vista+ 需管理員權限才能收到某些裝置通知,參考文章 102737 Manifest 設定。
  5. 執行緒安全: 訊息在 UI 執行緒,耗時操作 (掃描、拷貝) 應 PostMessage 到工作執行緒或 AfxBeginThread。

擴展:註冊裝置通知 (更精確控制)

若需針對特定裝置介面 GUID (如特定廠商 U 盤) 通知,可用 RegisterDeviceNotification 註冊 DEV_BROADCAST_DEVICEINTERFACE,取消註冊用 UnregisterDeviceNotification。但對通用 U 盤偵測,WM_DEVICECHANGE + DBT_DEVTYP_VOLUME 最簡便。

參考 MSDN 範例:Detecting Media Insertion or Removal。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved