這裡是使用WndProc()來監聽Windows的訊息,
WM_DEVICECHANGE是 Windows 系統發送給應用程序的消息,用於通知設備的插入、移除或狀態改變。
例如,當你插入或拔出 USB 設備時,系統會發送這條消息。
WM_DEVICECHANGE訊息
- wParam:表示设备事件的类型(例如插入、移除等)。
- lParam:指向一個結構體,包含事件的詳細信息(比如設備類型、設備路徑等)。
常數名稱 | 數值(十六進位) | 說明 |
---|---|---|
DBT_DEVICEARRIVAL | 0x8000 | 裝置已插入(例如:USB 插入) |
DBT_DEVICEREMOVECOMPLETE | 0x8004 | 裝置已被移除 |
DBT_DEVNODES_CHANGED | 0x0007 | 裝置樹發生變更(新增或移除裝置) |
DBT_DEVICEQUERYREMOVE | 0x8001 | 請求移除裝置(應用程式可拒絕) |
DBT_DEVICEQUERYREMOVEFAILED | 0x8002 | 裝置移除請求失敗(使用者或應用程式拒絕) |
DBT_DEVICETYPEDATA | 0x8005 | 特定裝置類型的事件(例如媒體更換) |
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);
}
留言
張貼留言