MFC U盘 拔插检测

今天在项目中看到了这一段代码,该代码用来检测USB设备的连接情况,于是就有一点好奇是如何做到的。在搜索资料后发现是用WM_DEVICECHANGE消息实现的。下面就来讲如何实现的。
该文章转载自博客园:MFC U盘检测
首先先了解WM_DEVICECHANGE消息,在微软的官方文档中指出了该消息的消息响应函数为OnDeviceChange();CWnd::OnDeviceChange说明
说明:该函数是被MFC框架调用的,调用此成员函数来向应用程序或设备驱动程序通知设备或者计算机的硬件配置发生了更改。另外关于WM_DEVICECHANGE更详细的说明和例子可以参考微软的官方文档处理WM_DEVICECHANGE
下面具体说明下如何U盘拔插检测。
新建工程如下:
运行后的效果如下图:
在这里插入图片描述
在CheckUSBDlg.h中添加如下代码:

// WM_DEVICECHANGE的消息响应函数
afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD_PTR dwData);
// EDIT 控件变量,显示拔插信息
CEdit m_USBEdit;
// 重载WindowProc窗口过程函数,本质上依然是对WM_DEVICECHANGE的处理
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

具体实现,在CheckUSBDlg.cpp中添加如下代码:
1.首先需要包含这两个头文件

#include <dbt.h>
#include <winioctl.h> 

#include <dbt.h>的作用:使用系统服务,本工程是与USB相关的,但是具体笔者也不是很清楚。欢迎大家指导。具体可以参考微软官方文档关于dbt.h的说明
#include <winioctl.h> 的作用:网上解释是DDK驱动开发,设备控制之类的。大家可以参考微软官方文档关于winioctrl.h的说明
2.接下来在消息映射表中添加消息映射关系,因为WM_DEVICECHANGE是系统消息,所以这样添加:

ON_WM_DEVICECHANGE()

3.消息映射函数OnDeviceChange()函数的实现:

BOOL CCheckUSBDlg::OnDeviceChange(UINT nEventType, DWORD_PTR dwData)
{
	CString detectMsg;
	// 用作与通过WM_DEVICECHANGE消息报告的设备事件相关信息的标准头
	PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)dwData;

	// nEventType:相当于wParam
	switch (nEventType)
	{  
	case DBT_DEVICEREMOVECOMPLETE: // 设备卸载或者拔出
	{
		// 判断当前USB设备是否是逻辑卷
		if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)//逻辑卷
		{
			// 包含有关逻辑卷的信息
			PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
			// 判断当前逻辑卷的类型
			switch (lpdbv->dbcv_flags) 
			{
			case 0:                //U盘
			{
				// 输出U盘的拔插信息
				CString decDriver;
				decDriver = FirstDriveFromMask(lpdbv->dbcv_unitmask);
				detectMsg.Format(_T("检测到U盘:[%s]拔出!"), decDriver.GetBuffer());
				m_USBEdit.SetWindowText(detectMsg);
			}
			break;
			case DBTF_MEDIA:    //光盘

				break;
			}
		}
	}
	break;
	case DBT_DEVICEARRIVAL:    // 系统检测到新设备
	{
		if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)//逻辑卷
		{
			PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
			switch (lpdbv->dbcv_flags)
			{
			case 0:                //U盘
			{
				CString decDriver;
				decDriver = FirstDriveFromMask(lpdbv->dbcv_unitmask);
				detectMsg.Format(_T("检测到U盘:[%s]插入!"), decDriver.GetBuffer());
				m_USBEdit.SetWindowText(detectMsg);
			}
			break;
			case DBTF_MEDIA:    //光盘
				break;
			}
		}
	}
	break;
	}
	return TRUE;


}

说明OnDeviceChange()的两个参数相当于wParam和lParam.
在上述代码中的结构体说明和各种宏的说明可以参考微软的官方文档dbt.h说明.
4.使用窗口过程函数WindowProc实现如下:

CString detectMsg;

switch (message)
{
	//WM_DEVICECHANGE,系统硬件改变发出的系统消息
	case WM_DEVICECHANGE:
	{
		PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
		switch (wParam)
		{
		case WM_DEVICECHANGE:
			break;
		case DBT_DEVICEARRIVAL://设备检测结束,并且可以使用
		{
			if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)//逻辑卷
			{
				PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
				switch (lpdbv->dbcv_flags)
				{
				case 0:                //U盘
				{
					CString decDriver;
					decDriver = FirstDriveFromMask(lpdbv->dbcv_unitmask);
					detectMsg.Format(_T("检测到U盘:[%s]插入!"), decDriver.GetBuffer(0));
					m_USBEdit.SetWindowText(detectMsg);
				}
				break;
				case DBTF_MEDIA:    //光盘
					break;
				}
			}
		}
		break;
		case DBT_DEVICEREMOVECOMPLETE://设备卸载或者拔出
		{
			if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)//逻辑卷
			{
				PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
				switch (lpdbv->dbcv_flags)
				{
				case 0:                //U盘
				{
					CString decDriver;
					decDriver = FirstDriveFromMask(lpdbv->dbcv_unitmask);
					detectMsg.Format(_T("检测到U盘:[%s]拔出!"), decDriver.GetBuffer(0));
					m_USBEdit.SetWindowText(detectMsg);
				}
				break;
				case DBTF_MEDIA:    //光盘

					break;
				}
			}
		}
		break;
		}
	}
	break;
}

说明:上面结构体的说明大家可以参考微软的官方文档,这里不再说明。最终效果如下:
移除设备:
在这里插入图片描述
插入设备:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值