USB设备热插拔处理--基于C++Bulild事件
背景描述:
USB设备的即插即用的属性,使得在实际应用中经常会遇到USB设备在程序运行过程中被移除或插入,应用程序需要该事件进行处理。
基于C++ Builder 1.重载WndProc函数 void __fastcall TForm1::WndProc(TMessage &Message) { if(Message.Msg == WM_DEVICECHANGE) //帮助里面有这个消息的详细说明 { if(Message.WParam == DBT_DEVICEARRIVAL) { Memo1->Lines->Add("发现USB设备插入!"); } else if(Message.WParam == DBT_DEVICEREMOVECOMPLETE) { Memo1->Lines->Add("USB设备被拔出!"); } else { Memo1->Lines->Add("WM_DEVICECHANGE"); } } TForm::WndProc(Message); }
2.在FormCreat中(或其他合适的地方添加设备注册) // 这里只是为了得到HID设备的GUID,实际上可以省掉该步骤 typedef __stdcall void(*pGetHidGuid)(GUID* HidGuid); GUID HidGuid; pGetHidGuid HidD_GetHidGuid; HINSTANCE h; if ((h = LoadLibrary("hid.dll"))==NULL) { return; } HidD_GetHidGuid=(pGetHidGuid)GetProcAddress(h,"HidD_GetHidGuid"); if(HidD_GetHidGuid==NULL) { return; } HidD_GetHidGuid(&HidGuid); // 这里才是注册USB热插拔消息 DEV_BROADCAST_DEVICEINTERFACE DevInt; memset(&DevInt,0,sizeof(DEV_BROADCAST_DEVICEINTERFACE)); DevInt.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); DevInt.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; DevInt.dbcc_classguid = HidGuid; RegisterDeviceNotification(Handle,&DevInt,DEVICE_NOTIFY_WINDOW_HANDLE);
注意事项: 1,一定要在重载的WndProc结束的时候调用基类的WndProc函数继续处理,否则将影响其他功能; 2.HidD_GetHidGuid需要调用动态链接库hid.dll(系统自带了)来完成; 3.Handle从基类继承来,这里无需关心; 4.需要引用系统定义的头文件dbt.h; 5.不同的设备有不同的GUID,所有的HID设备的GUID相同; 6.这里用HID来做例子,其他设备可以直接指定GUID(如果不指定GUID,则为全部USB设备);
基于VC6.0 1.在框体代码找到中加入BEGIN_MESSAGE_MAP/END_MESSAGE_MAP,并加入一行 BEGIN_MESSAGE_MAP(CMainDlg, CDialog) ON_MESSAGE(WM_DEVICECHANGE, OnDeviceChange) END_MESSAGE_MAP() 说明: WM_DEVICECHANGE是Windows定义的设备改变事件,定义在DBT.h中,其值为0x219 OnDeviceChange是用户定义的回调函数.
2.添加回调函数 BOOL CMainDlg::OnDeviceChange(UINT nEventType, DWORD dwData) { ShowInfo("Device Changed"); //显示函数(用户定已定义的,调试用) return TRUE; } 至此,如果有设备插入及移除已经可以通知到窗体了,但只会收到DBT_DEVNODES_CHANGED事件 (通过nEventType == 0x0007),无法得到详细信息;
3.注册设备 在stdafx.h的第1行加入 #define WINVER 0x0500 注意:一定要加在前边,否则编译会出错 在窗体文件初始化函数OnInitDialog(或其他适当的函数中也行)中添加: GUID HidGuid; DEV_BROADCAST_DEVICEINTERFACE DevBroadcastDeviceInterface; HidD_GetHidGuid(&HidGuid); //获取HID设备的接口类GUDI DevBroadcastDeviceInterface.dbcc_size=sizeof(DevBroadcastDeviceInterface); DevBroadcastDeviceInterface.dbcc_devicetype=DBT_DEVTYP_DEVICEINTERFACE; DevBroadcastDeviceInterface.dbcc_classguid=HidGuid; //注册设备改变时收到通知 RegisterDeviceNotification(m_hWnd, &DevBroadcastDeviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE);
4.修改OnDeviceChange函数 BOOL CAaaDlg::OnDeviceChange(UINT nEventType, DWORD dwData) { if(nEventType == DBT_DEVICEARRIVAL) { ShowInfo("设备已插入"); } else if(nEventType == DBT_DEVICEREMOVECOMPLETE) { ShowInfo("设备已移除"); } return TRUE; }
5.此时系统可以正常捕获到详细的信息DBT_DEVICEARRIVAL/DBT_DEVICEREMOVECOMPLETE等; 继续修改OnDeviceChange函数,以添加期望功能; 注意事项: m_hWnd(消息接收窗口的句柄)从基类继承;