【wxWidgets】【响应Windows消息】【监听WM_DEVICECHANGE消息、解决监听不到DBT_DEVICEARRIVAL的问题、监测USB设备拔插】

缘由:在修改一份旧代码,是基于wxWidgets开发的,使用VS2017编译。修改过程中,发现wxWidgets需要响应WM_DEVICECHANGE消息,用来监测USB设备的拔插,但是,进一步发现,如果只是依靠wxWidgets本身提供的功能是不能知道USB设备插入(DBT_DEVICEARRIVAL)事件的。这其实涉及到几方面问题了。

1,wxWidgets怎么拦截/监听/响应Windows的消息?

只要在wxFrame的继承类重写下面MSWWindowProc函数即可,比如

//如果有必要就 #include <Windows.h>

WXLRESULT ProjectWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
	wxLogDebug(wxT("MSWWindowProc nMsg=%x,%x %x"), nMsg, wParam, lParam);
	if (WM_PAINT == message) {
		//...这里就可以额外响应WM_PAINT消息了。
	}
	return wxFrame::MSWWindowProc(message, wParam, lParam);
}

2,拦截/监听 WM_DEVICECHANGE消息

记住要包含头文件

#include <Dbt.h>
#include <usb.h>
#include <usbuser.h>
#include <usbiodef.h>

实践表明,单单就照着下面这么写,可以监听到WM_DEVICECHANGE,能知道DBT_DEVNODES_CHANGED,但是不能获取到DBT_DEVICEARRIVAL和DBT_DEVICEREMOVECOMPLETE 事件。

WXLRESULT ProjectWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
	//wxLogDebug(wxT("MSWWindowProc %08x %08x %08x"), nMsg, wParam, lParam);
	if ( WM_DEVICECHANGE == message) 
	{    
		//注意,此时,只能获取到DBT_DEVNODES_CHANGED事件
		if ( DBT_DEVICEARRIVAL == wParam) {
			wxLogDebug(wxT("system detected a new device"));
		}
		else if( DBT_DEVICEREMOVECOMPLETE == wParam ) {
			wxLogDebug(wxT("device is gone"));
		}
		else if( DBT_DEVNODES_CHANGED == wParam ) {
			wxLogDebug(wxT("device nodes changed"));
		}
	}
	return wxFrame::MSWWindowProc(message, wParam, lParam);
}

3,怎么知道USB设备拔插事件?

基于WM_DEVICECHANGE 要区分DBT_DEVICEARRIVAL和DBT_DEVICEREMOVECOMPLETE事件,怎么实现?

关键之处就是,要额外注册USB设备事件,完整版如下

//Howard 2020-04-01
WXLRESULT ProjectWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
	//wxLogDebug(wxT("MSWWindowProc nMsg=%x,%x %x"), nMsg, wParam, lParam);
	if (WM_PAINT == message) {
		//仅仅方便测试,关键就是要注册!!
		static bool isNeedRegister = true;
		if (isNeedRegister) {
			isNeedRegister = false;

			DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
			ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
			NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
			NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
			NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
			HWND hWnd = (HWND)this->GetHWND();
			RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
		}
	}

	else if ( WM_DEVICECHANGE == message)
	{
		wxLogDebug(wxT("WM_DEVICECHANGE %x %x"), wParam, lParam);
		if ( DBT_DEVICEARRIVAL == wParam) {
			wxLogDebug(wxT("system detected a new device"));//USB设备插入
		}
		else if( DBT_DEVICEREMOVECOMPLETE == wParam ) {
			wxLogDebug(wxT("device is gone"));//USB设备拔出
		}
		else if( DBT_DEVNODES_CHANGED == wParam ) {
			wxLogDebug(wxT("device nodes changed"));
		}
	}
	return wxFrame::MSWWindowProc(message, wParam, lParam);
}

 

4,特别说明,设备类型与GUID

特别强调,对于监听HID设备,使用的GUID是不同的。不同类型设备,对应的GUID是有明确规定的。

Common Device Class GUIDs
ClassGUIDDevice Description
CDROM4D36E965-E325-11CE-BFC1-08002BE10318CD/DVD/Blu-ray drives
DiskDrive4D36E967-E325-11CE-BFC1-08002BE10318Hard drives
Display4D36E968-E325-11CE-BFC1-08002BE10318Video adapters
FDC4D36E969-E325-11CE-BFC1-08002BE10318Floppy controllers
FloppyDisk4D36E980-E325-11CE-BFC1-08002BE10318Floppy drives
HDC4D36E96A-E325-11CE-BFC1-08002BE10318Hard drive controllers
HIDClass745A17A0-74D3-11D0-B6FE-00A0C90F57DASome USB devices
13946BDD1FC1-810F-11D0-BEC7-08002BE2092FIEEE 1394 host controller
Image6BDD1FC6-810F-11D0-BEC7-08002BE2092FCameras and scanners
Keyboard4D36E96B-E325-11CE-BFC1-08002BE10318Keyboards
Modem4D36E96D-E325-11CE-BFC1-08002BE10318Modems
Mouse4D36E96F-E325-11CE-BFC1-08002BE10318Mice and pointing devices
Media4D36E96C-E325-11CE-BFC1-08002BE10318Audio and video devices
Net4D36E972-E325-11CE-BFC1-08002BE10318Network adapters
Ports4D36E978-E325-11CE-BFC1-08002BE10318Serial and parallel ports
SCSIAdapter4D36E97B-E325-11CE-BFC1-08002BE10318SCSI and RAID controllers
System4D36E97D-E325-11CE-BFC1-08002BE10318System buses, bridges, etc.
USB36FC9E60-C465-11CF-8056-444553540000USB host controllers and hubs

参考资料:

https://docs.microsoft.com/en-us/windows/win32/devio/detecting-media-insertion-or-removal

https://stackoverflow.com/questions/30399992/wm-devicechange-received-but-not-dbt-devicearrival-in-my-qt-app

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值