Win32程序与Qt程序对U盘的探测实践

在Windows操作系统下,所有的事件都是以消息为驱动的,因此,当我们插U盘和拔U盘时,也是触发了Windows的消息,我们对此消息进行监听并接收该消息,就可以探测对U盘的插拔。


01


Win32程序

对于消息的监听,熟悉Windows中Win32程序原理的你,一定非常熟悉,其六大步骤如下:

1. 声明消息类(WNDCLASS)

2. 注册消息类(RegisterClass)

3. 创建窗口(CreateWindow)

4. 获取消息队列(GetMessage)

5. 消息传送(TranslateMessage)

6. 消息派发(DispatchMessage)

在声明消息类WNDCLASS时,设置消息回调wc.lpfnWndProc为我们自己的函数,即可以接收到系统的消息到该函数中。

以上过程,在main函数中的源码如下:

int _tmain(int argc, _TCHAR* argv[])
{
	isNumber("5.8.");

	WNDCLASS wc;
	ZeroMemory(&wc, sizeof(wc));
	wc.lpszClassName = TEXT("myusbmsg");
	wc.lpfnWndProc = WndProc;

	RegisterClass(&wc);
	HWND h = CreateWindow(TEXT("myusbmsg"), TEXT(""), 0, 0, 0, 0, 0,
		0, 0, GetModuleHandle(0), 0);
	MSG msg;
	while (GetMessage(&msg, 0, 0, 0) > 0) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return 0;
}

要接收U盘的插拔消息,就可以在我们设置的回调函数中判断,假如我们的回调函数声明如下:

LRESULT CALLBACK WndProc(HWND h, UINT msg, WPARAM wp, LPARAM lp);

首先得判断收到的消息msg是不是U盘的插拔,因为Windows的消息非常多,因此得屏蔽掉无关的消息,只处理我们想接受的消息。U盘的插拔所触发的消息消息为 WM_DEVICECHANGE 消息,不管是插入U盘,韩式拔掉U盘,都会触发 WM_DEVICECHANGE 消息。

Windows的消息回调函数还会携带WPARAM wp, LPARAM lp连个参数,可以帮助我们判断U盘是插入还是拔出,以及U盘插入后是

哪个盘符,其详细解释如下:

  • wp的值为 DBT_DEVICEARRIVAL 时,表示U盘插入了。其值为 DBT_DEVICEREMOVECOMPLETE 时,表示U盘拔出了。

  • 将lp进行转换 DEV_BROADCAST_VOLUME* p = (DEV_BROADCAST_VOLUME*)lp;得到DEV_BROADCAST_VOLUME的指针p,当 p->dbcv_devicetype == DBT_DEVTYP_VOLUME 时,表示卷标发生变化,即可以知道U盘发生了插入或拔出。

  • 通过 p->dbcv_unitmask 可以根据其位操作中1的标识位判断具体是哪个盘发生了插入或拔出,其判断函数如下:

char FirstDriveFromMask(ULONG unitmask)

{

char i;

for (i = 0; i < 26; ++i)

{

if (unitmask & 0x1)

break;

unitmask = unitmask >> 1;

}

return (i + 'A');

}

通过代码一目了然可知,当p->dbcv_unitmask为0x1时为A盘,为0x10时为B盘,为0x100时为C盘,为0x1000时为D盘...以此类推。


以下奉上接收消息的函数,以及U盘插拔判断的逻辑,如下仅供参考:

LRESULT CALLBACK WndProc(HWND h, UINT msg, WPARAM wp, LPARAM lp)

{

/*

* system uses the WM_DEVICECHANGE message to notify device is changed(USB is inserted or removed).

*/

if (msg == WM_DEVICECHANGE) {

printf("注意---Msg-Change===wp=%d---lp=%d\n", wp, lp);


/*

* #define DBT_DEVNODES_CHANGED 0x0007

* Message = WM_DEVICECHANGE

* wParam  = DBT_DEVNODES_CHANGED

* lParam  = 0

*

*      send when configmg finished a process tree batch. Some devnodes

*      may have been added or removed. This is used by ring3 people which

*      need to be refreshed whenever any devnode changed occur (like

*      device manager). People specific to certain devices should use

*      DBT_DEVICE* instead.

*

* The upon windows-msg-param is received when device list is changed, but this time

* system don't know which device is add or remove, after second signal received, the

* below wparam can judge U-Disk or other device.

*/


/*

* The below wparam DBT_DEVICEARRIVAL(system detected a new device) & DBT_DEVICEREMOVECOMPLETE(device is gone)

* can just detect U-Disk inserted or removed(VOLUME List Changed), other device didn't show in volume list

* will not receive DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE(Like Mouse and KeyBorad with not line).

*/

if ((DWORD)wp == DBT_DEVICEARRIVAL) {

DEV_BROADCAST_VOLUME* p = (DEV_BROADCAST_VOLUME*)lp;

if (p->dbcv_devicetype == DBT_DEVTYP_VOLUME) {

char disk = FirstDriveFromMask(p->dbcv_unitmask);

printf("注意---%c盘插进来了\n", disk);

}

}

else if ((DWORD)wp == DBT_DEVICEREMOVECOMPLETE) {

DEV_BROADCAST_VOLUME* p = (DEV_BROADCAST_VOLUME*)lp;

if (p->dbcv_devicetype == DBT_DEVTYP_VOLUME) {

char disk = FirstDriveFromMask(p->dbcv_unitmask);

printf("注意---%c盘被拔掉了\n", disk);

}

}

return TRUE;

}

else return DefWindowProc(h, msg, wp, lp);

}

以上即为win32接收U盘插拔的监听探测代码。

02


Qt程序

下面介绍Qt如何监听探测U盘的插拔消息,由于Windows系统是以消息为驱动的,因此,想用Qt接受监听U盘的插拔消息,说到底其实就是Qt如何接收监听Windows的消息。

在Qt4中,接收监听Windows消息的Qt函数声明如下:

bool winEvent(MSG *message, long *result);

 在Qt5之后,函数声明变为了如下:

bool nativeEvent(const QByteArray &eventType, void *message, long *result);

对以上两个函数中的message参数进行如下处理:

MSG* msg = reinterpret_cast<MSG*>(message);

即可得到Windows消息的结构体MSG,其定义如下:

typedef struct tagMSG {

HWND hwnd;

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time;

POINT pt;

} MSG

因此就可以得到UINT message、WPARAM wParam 以及 LPARAM lParam; 接下来的处理就如同win32中的回调函数WndProc一样了。


以上不仅仅是Qt对U盘插拔消息的监听,通过以上Qt的winEvent或nativeEvent函数的重写,以及相应参数的转换处理,Qt可以接收监听所有的Windows的消息,说到这里,对Win32了解的你,一定非常熟悉了。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值