當裝置被插入/拔出的時候,WINDOWS會向每個窗體發送WM_DEVICECHANGE 消息,當消息的wParam 值等于 DBT_DEVICEARRIVAL 時,表示Media裝置被插入并且已經可用;如果wParam值等于DBT_DEVICEREMOVECOMPLETE,表示Media裝置已經被移出。
它們的lParam都指向一個 DEV_BROADCAST_HDR結構體,其原形如下:
struct _DEV_BROADCAST_HDR { /* */
DWORD dbch_size;
DWORD dbch_devicetype;
DWORD dbch_reserved;
};
這個結構體僅僅是一個“頭”(HDR),其後還有附加資料,dbch_size表示結構體執行個體的位元組數,當其中的dbch_devicetype字段值等于DBT_DEVTYP_VOLUME時,表示目前裝置是邏輯驅動器,且lParam實際上指向的應該是DEV_BROADCAST_VOLUME 結構體執行個體(真佩服這種邏輯),DEV_BROADCAST_VOLUME 結構體原形如下:
struct _DEV_BROADCAST_VOLUME { /* */
DWORD dbcv_size;
DWORD dbcv_devicetype;
DWORD dbcv_reserved;
DWORD dbcv_unitmask;
WORD dbcv_flags;
};
其中dbcv_unitmask 字段表示目前改變的驅動器掩碼,第一位表示驅動器号A,第二位表示驅動器号B,第三位表示驅動器号C,以此類推…… dbcv_flags 表示驅動器的類别,如果等于1,則是CD光牒驅動器;如果是2,則是網絡驅動器;如果是硬碟、U盤則都等于0
是以,我隻需要在程式中捕捉WM_DEVICECHANGE 消息,然後根據具體情況去處理即可。
下面看我的一段重載WndProc處理WM_DEVICECHANGE的過程。。
void __fastcall TMainForm::WndProc(TMessage &Message)
{
if( wFlag == TRUE)
{
if(Message.Msg == WM_DEVICECHANGE)
{
switch (Message.WParam)
{
case DBT_DEVICEARRIVAL:
{
PDEV_BROADCAST_HDR pstDevHdr = (PDEV_BROADCAST_HDR)Message.LParam;
if(pstDevHdr->dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME pstDev = (PDEV_BROADCAST_VOLUME)Message.LParam;
if(pstDev->dbcv_flags == 0)
{
mmoMonLog->Lines->Add("USB裝置插入");
mmoMonLog->Lines->Add("目前USB盤符為" + AnsiString(ScanUsbDisk())+"盤");
}
}
}
break;
case DBT_DEVICEREMOVECOMPLETE:
{
mmoMonLog->Lines->Add("USB裝置移除");
}
break;
default:
break;
}
}
}
TForm::WndProc(Message);
}