开发windows MFC 应用程序时,经常会操作一些硬件设备,那么如何实现设备的热插拔功能呢,下面给出具体操作步骤:
1,给要实现设备热插拔的窗体/界面 添加 ON_WM_DEVICECHANGE() 消息,如下在 BEGIN_MESSAGE_MAP (...)
与END_MESSAGE_MAP() 之间加入 一行“ ON_WM_DEVICECHANGE() ”
BEGIN_MESSAGE_MAP(CServoTestDlg, CDialog)
...
ON_WM_DEVICECHANGE()
...
END_MESSAGE_MAP()
2,给窗体注册 插拔事件,一般可在 OnInitDialog()函数 中加入 ,代码如下:
BOOL xxx::OnInitDialog()
{
int i,j;
CDialog::OnInitDialog();
...
//注册插拔事件
HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
for (int i = 0; iGetSafeHwnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if (!hDevNotify)
{
return FALSE;
}
}
return TRUE;
}
上面中会用到一些常量 GUID_DEVINTERFACE_LIST ,这里定义了 设备的一些信息,如下:
static const GUID GUID_DEVINTERFACE_LIST[] =
{
// GUID_DEVINTERFACE_USB_DEVICE
{ 0xA5DCBF10, 0x6530, 0x11D2,{ 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },
// GUID_DEVINTERFACE_HID,
{ 0x4D1E55B2, 0xF16F, 0x11CF,{ 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },
};
上面显示这个窗体关事的设备是USB设备,HID设备。
3,实现 OnDeviceChange 函数,其详细实现步骤有,一,在对应的 xxxdlg.h 文件中加入
afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD_PTR dwData); 二,在xxxdlg.cpp 文件中实现 OnDeviceChange 函数功能:
PDEV_BROADCAST_DEVICEINTERFACE pdbi;
PDEV_BROADCAST_PORT dhr;
DEV_BROADCAST_DEVICEINTERFACE* dbd;
//设备状态改变时的处理函数
BOOL CServoTestDlg::OnDeviceChange(UINT nEventType, DWORD_PTR dwData)
{
dbd = (DEV_BROADCAST_DEVICEINTERFACE*) dwData;
//dwData是一个指向DEV_BROADCAST_DEVICEINTERFACE结构体的指针,
//在该结构体中保存了设备的类型、路径名等参数。通过跟我们指定设备
//的路径名比较,即可以判断是否是我们指定的设备拔下或者插入了。
pdbi = (PDEV_BROADCAST_DEVICEINTERFACE)dwData;
dhr = (PDEV_BROADCAST_PORT )dwData;
switch (nEventType) //参数nEventType中保存着事件的类型
{
//设备连接事件
case DBT_DEVICEARRIVAL:
if (pdbi->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)dhr;
CString name(lpdbv->dbcp_name);
if ( name.Find(L"VID_0483") && name.Find(L"PID_5740") )
{
// OnBnClickedConnectDevice(); // 插入后在操作
}
}
return TRUE;
// 设备拔出事件
case DBT_DEVICEREMOVECOMPLETE:
if (pdbi->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)dhr;
CString name(lpdbv->dbcp_name);
if ( name.Find(L"VID_0483") && name.Find(L"PID_5740") )
{
if (IsDeviceOpened == TRUE )
{
// OnBnClickedReleaseDevice(); // 拔出后的操作
}
}
}
return TRUE;
default: return TRUE;
}
}
上面的代码加入了对usb 设备的VID 与 PID的判定,以确定是否是所关心的设备的插入/拔出。
实现以上三步,就可以实现设备的热插拔功能了!!