如何檢測到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;
}
問題得到圓滿解決。

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