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);
}

留言

2025

05-27C# 多執行緒程(Multithreading)【五】task
05-21C# 多執行緒程(Multithreading)【四】ThreadPool
05-19C# 多執行緒程(Multithreading)【三】UI操作
05-19C# 多執行緒程(Multithreading)【二】Thread
05-12C# 多執行緒程(Multithreading)【一】
05-05WMI (Windows管理規範)與WQL(WMI 查詢語言)
04-30WndProc 視窗處理函數【三】USB裝置插入/移除偵測
04-29WndProc 視窗處理函數【二】Windows Messages (WM_*) 分類清單
04-29WndProc 視窗處理函數【一】

2024

11-27SPI Flash 操作 (Read/Write/Erase)
11-19Rotary Encoder Switch 旋轉編碼開關
11-14Command Line Interface - CLI via UART
11-14【STM32】USB HID - Volume Control
11-13【STM32】USB Custom HID
11-12【STM32】USB HID Keyboard + Mouse
11-12【STM32】USB HID Keyboard
11-12【STM32】USB HID Mouse
10-15SSD1306 128x64 OLED 【五】Wokwi Animator
09-2432F429IDISCOVERY - - LTDC [3] + FMC (SDRAM) + FatFS
09-2432F429IDISCOVERY - - LTDC [2] + FMC (SDRAM)
09-20STM32 + FatFs + SD card via SPI【三】FatFS指令操作II
09-19STM32 + FatFs + SD card via SPI【二】FatFS指令操作
09-18STM32 + FatFs + SD card via SPI【一】移植FatFS
09-0232F429IDISCOVERY - - LTDC [1]
04-17SSD1306 128x64 OLED 【四】Adafruit / GFX Library
04-17Arduino - Serial Plotter繪圖儀
04-16SSD1306 128x64 OLED 【三】
04-15SSD1306 128x64 OLED 【二】 Datasheet
04-12SSD1306 128x64 OLED 【一】I2C版本
03-20【freeRTOS】vTaskDelay 與 vTaskDelayUntil 的差異
03-19【freeRTOS】API功能列表
03-18【freeRTOS】Day1
03-08MBR和Blank project的差別
03-05刪除註冊檔registry的資料
02-27DFU over Bluetooth Low Energy
02-27nRF Util - 使用手冊
02-26nRF Command Line Tools
02-20建立BootLoader settings
02-19Secure DFU packet (ZIP) build 建立含袐鑰的Zip檔
02-19Secure DFU via BLE
02-19Secure DFU via UART
02-16nRF Util 安裝
01-16nRF52840 ic升級成nRF52840 Dongle的程式

2023

11-21[ SEGGER Embedded Studio ] 新增header files
11-21[ SEGGER Embedded Studio ] 編譯nRF52840時遇到的問題
11-07Arduino Nano ESP32 - Debugging除錯模式
11-03Git快速入手 - 使用Git GUI
10-30Git快速入手 - 使用Git Bash
10-12程式碼高亮顯示 -- google-code-prettify

2022

11-30[EZ-PD] CCG6DF CCG6SF的Host SDK遇到編譯錯誤(一)

2019

05-27[ Eagle PCB ] 合板成品
05-23#CASE_001_USB_TOOL_RL78_G12
05-22[ Eagle PCB ] 初次洗板
05-21[ Eagle PCB ] Panelize 併板
05-20[ Eagle PCB ] 建立自己的Library及元件
05-20[ Eagle PCB ] 添加library及元件
05-20[ Eagle PCB ] Introduce

2018

04-25[ TCP test Tool ] 好用的TCP Server/Client工具
01-16RZ/A1H -[0]- Renesas RZ/A1H YR0K77210S009BE BSP環境架設

2017

12-11EZ USB Suit使用JLink online debug FX3
10-20RL78 -[12]- CS+_CACX_Lab5_LowPower mode
10-16RL78 -[11]- CS+_CACX_Lab4_ADC_溫度感測
10-13RL78 -[10]- CS+_CACX_Lab4_ADC_內部參考電壓
10-13RL78 -[9]- CS+_Lab3_I2C + MPU6050
10-13RL78 -[8]- CS+_Lab2_Uart transmit
10-12RL78 -[7]- Renesas Flash Programmer 獨立燒錄軟體
10-12RL78 -[6]- CS+_雜記
10-12RL78 -[5]- CS+_tracking variables on debug mode
10-12RL78 -[4]- CS+_顯示ROM與RAM的使用size
10-12RL78 -[3]- CS+_Lab1_Led blinking
10-12RL78 -[2]- CS+專案建立
10-12RL78 -[1]- 開發環境介紹
10-06ESP-01 -[0]- 硬體設置
10-06LinkIt 7688 program Renesas RL78/G12 by 1-wire
10-06LinkIt Smart 7688 -[3]- Build the firmware from source codes
10-06LinkIt Smart 7688 -[2]- 使用UART進入bootloader / kernel console
10-06LinkIt Smart 7688 -[1]- 使用SSH連接kernel console
10-06LinkIt Smart 7688 -[0]- 初次使用
07-14LinkIt Smart 7688 -[9]- Using MRAA SPI in Python
07-13LinkIt Smart 7688 -[8]- Using MRAA UART in Python
07-12LinkIt Smart 7688 -[7]- Using MRAA I2C in Python
07-12LinkIt Smart 7688 -[6]- Using MRAA PWM in Python
07-12LinkIt Smart 7688 -[5]- Using MRAA GPIO in Python
07-10LinkIt Smart 7688 -[4]- 雜記
06-29輕乳酪蛋糕 Cotton Cheesecake
06-26VirtualBox 的 Ubuntu與Windows 共用資料夾

2015

04-29偵測USB PnP