WndProc 視窗處理函數【三】USB裝置插入/移除偵測

這裡是使用WndProc()來監聽Windows的訊息,

WM_DEVICECHANGE是 Windows 系統發送給應用程序的消息,用於通知設備的插入、移除或狀態改變。

例如,當你插入或拔出 USB 設備時,系統會發送這條消息。


WM_DEVICECHANGE訊息

  • wParam:表示设备事件的类型(例如插入、移除等)。
  • 常數名稱 數值(十六進位) 說明
    DBT_DEVICEARRIVAL 0x8000 裝置已插入(例如:USB 插入)
    DBT_DEVICEREMOVECOMPLETE 0x8004 裝置已被移除
    DBT_DEVNODES_CHANGED 0x0007 裝置樹發生變更(新增或移除裝置)
    DBT_DEVICEQUERYREMOVE 0x8001 請求移除裝置(應用程式可拒絕)
    DBT_DEVICEQUERYREMOVEFAILED 0x8002 裝置移除請求失敗(使用者或應用程式拒絕)
    DBT_DEVICETYPEDATA 0x8005 特定裝置類型的事件(例如媒體更換)

  • lParam:指向一個結構體,包含事件的詳細信息(比如設備類型、設備路徑等)。
  • lParam 常用結構:DEV_BROADCAST_DEVICEINTERFACE


    當 wParam 是 DBT_DEVICEARRIVAL 或 DBT_DEVICEREMOVECOMPLETE 時,

    lParam 會指向一個 DEV_BROADCAST_HDR 結構,包含裝置類型與裝置名稱(裝置路徑 GUID)。

    public struct DEV_BROADCAST_HDR
    {
        public int dbch_size;        // 結構大小(含裝置名稱等)
        public int dbch_devicetype;  // 裝置類型(如 DBT_DEVTYP_DEVICEINTERFACE)
        public int dbch_reserved;    // 保留,通常為 0
    }
    

    dbch_devicetype

    常數名稱 數值(十六進位) 說明
    DBT_DEVTYP_OEM 0x00000000 OEM 裝置類型(較少使用)
    DBT_DEVTYP_DEVNODE 0x00000001 設備節點(不含裝置名稱)
    DBT_DEVTYP_VOLUME 0x00000002 卷(Volume)裝置,像是硬碟或 USB 隨身碟的邏輯磁碟區
    DBT_DEVTYP_PORT 0x00000003 埠(如 COM 或 LPT)
    DBT_DEVTYP_NET 0x00000004 網路資源
    DBT_DEVTYP_DEVICEINTERFACE 0x00000005 裝置介面(例如 USB 裝置)
    DBT_DEVTYP_HANDLE 0x00000006 特定裝置的 Handle(需配合 API 使用)
    DEV_BROADCAST_HDR hdr = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_HDR));
    
    switch (hdr.dbch_devicetype)
    {
        case DBT_DEVTYP_DEVICEINTERFACE:
            // USB、藍芽等裝置
            break;
        case DBT_DEVTYP_VOLUME:
            // 磁碟區插入或移除(例如 U 盤)
            break;
        case DBT_DEVTYP_PORT:
            // 串列埠變化(例如 COM3)
            break;
        default:
            // 其他裝置
            break;
    }
    


範例一

private const int WM_DEVICECHANGE = 0x0219;             // 裝置插入/移除
private const int DBT_DEVICEARRIVAL = 0x8000;           // 裝置插入
private const int DBT_DEVICEREMOVECOMPLETE = 0x8004;    // 裝置拔除

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_DEVICECHANGE)
    {
        int eventType = m.WParam.ToInt32();

        if (eventType == DBT_DEVICEARRIVAL)
        {
            //Console.WriteLine("裝置插入!");
            Debug.WriteLine("裝置插入!");
        }
        else if (eventType == DBT_DEVICEREMOVECOMPLETE)
        {
            //Console.WriteLine("裝置拔除!");
            Debug.WriteLine("裝置拔除!");
        }
    }

    base.WndProc(ref m);
}



範例二

private const int WM_DEVICECHANGE = 0x0219;             // 裝置插入/移除
private const int DBT_DEVICEARRIVAL = 0x8000;           // 裝置插入
private const int DBT_DEVICEREMOVECOMPLETE = 0x8004;    // 裝置拔除

private const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005;
private const int DBT_DEVTYP_VOLUME = 0x00000002;
private const int DBT_DEVTYP_PORT = 0x00000003;

public struct DEV_BROADCAST_HDR
{
    public int dbch_size;        // 結構大小(含裝置名稱等)
    public int dbch_devicetype;  // 裝置類型(如 DBT_DEVTYP_DEVICEINTERFACE)
    public int dbch_reserved;    // 保留,通常為 0
}

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_DEVICECHANGE)
    {
        int eventType = m.WParam.ToInt32();

        if (eventType == DBT_DEVICEARRIVAL)
        {
            //Console.WriteLine("裝置插入!");
            Debug.WriteLine("裝置插入!");
            DEV_BROADCAST_HDR hdr = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_HDR));
            
            switch (hdr.dbch_devicetype)
            {
                case DBT_DEVTYP_DEVICEINTERFACE:
                    // USB、藍芽等裝置
                    Debug.WriteLine("USB、藍芽等裝置");
                    break;
                case DBT_DEVTYP_VOLUME:
                    // 磁碟區插入或移除(例如 U 盤)
                    Debug.WriteLine("U 盤!");
                    break;
                case DBT_DEVTYP_PORT:
                    // 串列埠變化(例如 COM3)
                    Debug.WriteLine("串列埠變化");
                    break;
                default:
                    // 其他裝置
                    Debug.WriteLine("其他裝置");
                    break;
            }
        }
        else if (eventType == DBT_DEVICEREMOVECOMPLETE)
        {
            //Console.WriteLine("裝置拔除!");
            Debug.WriteLine("裝置拔除!");
        }
    }

    base.WndProc(ref m);
}

留言