如何检测到USB热拔插

最近在写一个程序,需要检测USB设备热拔插事件。百度了一下需要响应 WM_DEVICECHANGE这个消息。

响应函数申明:

afx_msg BOOL OnDeviceChange(WPARAM nEventType, DWORD dwData);

消息映射:

BEGIN_MESSAGE_MAP(CPadSkipDlg, CDialog)
	//{{AFX_MSG_MAP(CPadSkipDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_CBN_SELCHANGE(IDC_COMBO_ROW, OnSelchangeComboRow)
	ON_CBN_SELCHANGE(IDC_COMBO_COL, OnSelchangeComboCol)
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_BTN_START, OnBtnStart)
	ON_COMMAND(ID_MENU_CONFIG, OnMenuConfig)
	ON_COMMAND(ID_MENU_DRAW, OnMenuDraw)
	ON_COMMAND(ID_MENU_INT, OnMenuInt)
	ON_COMMAND(ID_MENU_TURN, OnMenuTurn)
	ON_BN_CLICKED(IDC_BTN_UPDATE_FRAME, OnBtnUpdateFrame)
	ON_WM_TIMER()
	ON_WM_DEVICECHANGE()							
	ON_MESSAGE(WM_STOP_READ, OnStopRead)
	ON_CBN_SELENDCANCEL(IDC_COMBO_COL, OnSelendcancelComboCol)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

响应函数实现:

BOOL CPadSkipDlg::OnDeviceChange(WPARAM nEventType, DWORD dwData)
{
	PDEV_BROADCAST_DEVICEINTERFACE pdbi;
	CString szDevPathName;
	CString szFindDevPath;

	//dwData是一个指向DEV_BROADCAST_DEVICEINTERFACE结构体的指针,
	//在该结构体中保存了设备的类型、路径名等参数。通过跟我们指定设备
	//的路径名比较,即可以判断是否是我们指定的设备拔下或者插入了。
	pdbi=(PDEV_BROADCAST_DEVICEINTERFACE)dwData;
	szFindDevPath.Format(_T("VID_%04x&PID_%04x"), m_dwVentorID, m_dwProductID);

	switch(nEventType) //参数nEventType中保存着事件的类型
	{
		//设备连接事件
	case DBT_DEVICEARRIVAL:
		if(pdbi->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
		{			
			szDevPathName = pdbi->dbcc_name;						//保存发生状态改变的设备的路径名
			int nIndex1 = szDevPathName.Find(szFindDevPath, 7);

			if (nIndex1 != -1)
			{
				assert(!m_I2CmdObject.IsOpen());
				m_bUsbDevFound = TRUE;
				m_I2CmdObject.Open(m_dwVentorID, m_dwProductID);
				m_StatBar.SetPaneText(0, _T("HID设备连接成功"));
			}
		}
		return 1;

		//设备拔出事件
	case DBT_DEVICEREMOVECOMPLETE: 
		if(pdbi->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
		{
			szDevPathName = pdbi->dbcc_name;						//保存发生状态改变的设备的路径名
			int nIndex1 = szDevPathName.Find(szFindDevPath, 7);

			if (nIndex1 != -1)
			{
				assert(m_I2CmdObject.IsOpen());
				m_bUsbDevFound = FALSE;
				m_I2CmdObject.Close();
				m_StatBar.SetPaneText(0, _T("HID设备连接失败"));
				
			}
		}
		return 1;

	default:
		return 1;
	} 
}


OnDeviceChange函数的确响应了,但是nEventType一直为7,查了一下msdn。发现为DBT_DEVICECHANGED。很奇怪,于是百度了一下,发现需要注册设备事件,注册函数如下:

BOOL CPadSkipDlg::RegisterDevice()
{
	GUID HidGuid;
	HDEVNOTIFY hDeviceNotify;

	// mark,这里guid一定要选正确,不然此类设备找不到
	HidD_GetHidGuid(&HidGuid);

	DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
		
	ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
	NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
	NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
	NotificationFilter.dbcc_classguid = HidGuid;
	
	hDeviceNotify = RegisterDeviceNotification( 
		m_hWnd,                       // events recipient
		&NotificationFilter,        // type of device
		DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle
		);
	
	if ( NULL == hDeviceNotify ) 
	{
		return FALSE;
	}
	
	return TRUE;
}
问题得到圆满解决。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章