MFC枚举USB设备

本人初学VC++,尝试使用MFC来制作USB枚举,与大家分享经验。

本文利用根据微软的usbview源码,在Visual Stdio2015利用MFC写了USB枚举。首先利用SetupDiGetClassDevs()枚举GUID类型,这里的GUID选用的是GUID_DEVINTERFACE_USB_DEVICE,在usbiodef.h头文件中还有很多GUID。

添加头文件。

#include <hidsdi.h>
#include <usbiodef.h>
#include <initguid.h>
#include <winioctl.h>
#pragma comment(lib,"hid.lib")
#include <setupapi.h>
#pragma comment(lib,"setupapi.h")
#include <initguid.h>

下面代码是GUID的类型。 

DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \
             0xC0, 0x4F, 0xB9, 0x51, 0xED);

/* 3ABF6F2D-71C4-462a-8A92-1E6861E6AF27 */
DEFINE_GUID(GUID_DEVINTERFACE_USB_HOST_CONTROLLER, 0x3abf6f2d, 0x71c4, 0x462a, 0x8a, 0x92, 0x1e, \
             0x68, 0x61, 0xe6, 0xaf, 0x27);

/* 4E623B20-CB14-11D1-B331-00A0C959BBD2 */
DEFINE_GUID(GUID_USB_WMI_STD_DATA, 0x4E623B20L, 0xCB14, 0x11D1, 0xB3, 0x31, 0x00,\
             0xA0, 0xC9, 0x59, 0xBB, 0xD2);

/* 4E623B20-CB14-11D1-B331-00A0C959BBD2 */
DEFINE_GUID(GUID_USB_WMI_STD_NOTIFICATION, 0x4E623B20L, 0xCB14, 0x11D1, 0xB3, 0x31, 0x00,\
             0xA0, 0xC9, 0x59, 0xBB, 0xD2);

 接下来需要循环遍历所有的接口设备信息,使用函数SetupDiEnumDeviceInfo(handle, Count, &DeviceInfoData);

GetDeviceProperty()函数中的第三个参数选择可以得到设备的信息。这里获得了USB的名称、端口号等信息,该函数的内部结构如下。

BOOL CUSB_ENUMDlg::GetDeviceProperty(_In_ HDEVINFO DeviceInfoSet, _In_ PSP_DEVINFO_DATA DeviceInfoData, _In_ DWORD Property, _Outptr_ LPTSTR *ppBuffer)
{
	BOOL bResult;
	DWORD requiredLength = 0;
	DWORD lastError;

	if (ppBuffer == NULL)
	{
		return FALSE;
	}
	*ppBuffer = NULL;

	bResult = SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
		DeviceInfoData,
		Property,
		NULL,
		NULL,
		0,
		&requiredLength);
	lastError = GetLastError();

	if ((requiredLength == 0) || (bResult != FALSE && lastError != ERROR_INSUFFICIENT_BUFFER))
	{
		return FALSE;
	}

	*ppBuffer = (LPTSTR)ALLOC(requiredLength);

	if (*ppBuffer == NULL)
	{
		return FALSE;
	}

	bResult = SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
		DeviceInfoData,
		Property,
		NULL,
		(PBYTE)*ppBuffer,
		requiredLength,
		&requiredLength);
	if (bResult == FALSE)
	{
		FREE(*ppBuffer);
		*ppBuffer = NULL;
		return FALSE;
	}

	return TRUE;
}

制作MFC界面

 这是一个简单的按钮控件+列表控件,列表控件属性View改为Report模式。为列表控件添加成员变量m_listCtrl

CListCtrl m_listCtrl;

 在初始化成员函数中初始化列表控件。

BOOL CUSB_ENUMDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	DWORD dwstyle = m_listCtrl.GetExtendedStyle();
	dwstyle |= LVS_EX_GRIDLINES;
	dwstyle |= LVS_EX_FULLROWSELECT;
	m_listCtrl.SetExtendedStyle(dwstyle);
	//m_listCtrl.GetHeaderCtrl()->EnableWindow(FALSE);//不允许拖动列表头改变列宽
	
	CRect rcList;
	m_listCtrl.GetClientRect(rcList);//获得控件坐标属性
	m_listCtrl.InsertColumn(0, _T("Device Description"), LVCFMT_CENTER, 150);
	m_listCtrl.InsertColumn(1, _T("PORT"), LVCFMT_CENTER, 150);
	m_listCtrl.InsertColumn(2, _T("Path"), LVCFMT_CENTER, rcList.Width()-300);


	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

 添加枚举成员函数

BOOL CUSB_ENUMDlg::EnumerateAllDevicesWithGuid()
{
	LPTSTR DeviceDescName;
	SP_DEVINFO_DATA DeviceInfoData;
	SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
	GUID deviceId;
	DWORD strSize = 0, requiredSize = 0;
	ULONG DeviceInterfaceDetailSize;
	LPTSTR DeviceDriverName;
	TCHAR did[1024];
	LPTSTR locid;
	LPTSTR locdesc;
	//HidD_GetHidGuid(&deviceId);
	HDEVINFO handle;
	handle = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE,
		NULL,
		NULL,
		DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
	bool result1 = FALSE;
	bool result2 = FALSE;
	UINT Count = 0;
	DWORD error;
	do {
		
		BOOL success;
		DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
		success = SetupDiEnumDeviceInfo(handle, Count, &DeviceInfoData);
		if (success == FALSE)
		{
			break;
		}
			result1 = GetDeviceProperty(handle,
			&DeviceInfoData,
			SPDRP_DEVICEDESC,  //(0x00000000)
			&DeviceDescName);

			result1 = GetDeviceProperty(handle,
				&DeviceInfoData,
				SPDRP_DRIVER, //Registry Trees and Keys
				&DeviceDriverName);
			
			DWORD buffersize = 1024;
			DWORD req_bufsize = 0;
			DWORD DataT;
			if (!SetupDiGetDeviceInstanceId(handle,
				&DeviceInfoData,
				NULL,
				NULL,
				&req_bufsize)) {
				error = GetLastError();
			}
			SetupDiGetDeviceInstanceId(handle,
				&DeviceInfoData,
				did,
				req_bufsize,
				&requiredSize); //获得设备VID和PID
				
			if (!GetDeviceProperty(handle,
				&DeviceInfoData,
				SPDRP_LOCATION_PATHS,
				&locid))
				continue;
		
			if (!GetDeviceProperty(handle,
				&DeviceInfoData,
				SPDRP_LOCATION_INFORMATION,
				&locdesc
				))
				continue;

			DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
			result1 = SetupDiEnumDeviceInterfaces(handle,
				NULL,
				&GUID_DEVINTERFACE_USB_DEVICE,
				Count,
				&DeviceInterfaceData
				);
			SetupDiGetDeviceInterfaceDetail(handle,
				&DeviceInterfaceData,
				NULL,
				0,
				&strSize,
				NULL);
			requiredSize = strSize;
			char s[245];
			PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = (SP_DEVICE_INTERFACE_DETAIL_DATA *)s;
			DeviceInterfaceDetailData->cbSize= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
			result2 = SetupDiGetDeviceInterfaceDetail(handle,
				&DeviceInterfaceData,
				DeviceInterfaceDetailData,    //DeviceInterfaceDetailData->DevicePath为设备路径。
				strSize,
				&requiredSize,
				NULL
				);
			AddListCtrl(DeviceDescName, locdesc, DeviceInterfaceDetailData->DevicePath,Count);
			Count++;
	} while (result1);
	return TRUE;
}

 列表添加信息功能的函数AddListCtrl内容如下。

BOOL CUSB_ENUMDlg::AddListCtrl(CString Name, CString Port, CString Path,UINT nCount)
{
	m_listCtrl.InsertItem(nCount, Port);
	m_listCtrl.SetItemText(nCount, 1, Name);
	m_listCtrl.SetItemText(nCount, 2, Path);
	return TRUE;
}

最后实现效果如下图,单击按钮列表出现枚举设备信息。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值