最近项目要写一个MFC的外挂程序,要分别获取电脑上所有扫描枪的输入信息,这时我们就需要根据扫描枪的vid和pid进行区分,有一些同批次同型号的输入设备vid和pid会相同,我们可能需要设备实例路径进行区分,可以在设备管理器->键盘->点击设备查看,如图:
这里记录一下获取USB信息的代码,因为涉及到公司业务,只给出这部分我封装好的类,这是MFC下继承CDialogEx的类,C++只需要略作修改,核心代码为HID_FindAllDevices函数,我对记录pid,vid的vector进行了去重,设备有pid,vid相同的需要修改。
ScannerDlg.h
#pragma once
#include <vector>
#include <algorithm>
#include "afxwin.h"
// CScannerDlg 对话框
struct _VID_PID_
{
USHORT V_ID;
USHORT P_ID;
_VID_PID_(USHORT vid, USHORT pid)
{
V_ID = vid;
P_ID = pid;
}
bool operator==(const _VID_PID_ &other)
{
if (V_ID == other.V_ID && P_ID == other.P_ID)
return true;
return false;
}
};
class CScannerDlg : public CDialogEx
{
DECLARE_DYNAMIC(CScannerDlg)
public:
CScannerDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CScannerDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_SCANNER_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
private:
std::vector<_VID_PID_> vecVidPid;
void HID_FindAllDevices(unsigned short *FIFO_Length);
public:
CComboBox m_combo_scanner;
afx_msg void OnCbnDropdownComboScanner();
afx_msg void OnBnClickedOk();
};
ScannerDlg.cpp
// ScannerDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "ScannerDlg.h"
#include "afxdialogex.h"
#include <iostream>
#include <string>
#include <fstream>
#include <setupapi.h>
#include <devguid.h>
#include <winioctl.h>
#include <regstr.h>
#include <conio.h>
#pragma comment(lib,"setupapi.lib")
extern "C" {
#include <hidsdi.h>
};
// CScannerDlg 对话框
IMPLEMENT_DYNAMIC(CScannerDlg, CDialogEx)
CScannerDlg::CScannerDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_SCANNER_DIALOG, pParent)
{
}
CScannerDlg::~CScannerDlg()
{
}
void CScannerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_COMBO_SCANNER, m_combo_scanner);
}
BEGIN_MESSAGE_MAP(CScannerDlg, CDialogEx)
ON_CBN_DROPDOWN(IDC_COMBO_SCANNER, &CScannerDlg::OnCbnDropdownComboScanner)
ON_BN_CLICKED(IDOK, &CScannerDlg::OnBnClickedOk)
END_MESSAGE_MAP()
// CScannerDlg 消息处理程序
//查找所有vidpid
void CScannerDlg::HID_FindAllDevices(unsigned short *FIFO_Length)
{
GUID HidGuid;
HDEVINFO DevInfo;
HIDD_ATTRIBUTES DevAttributes;
SP_DEVICE_INTERFACE_DATA DevData;
PSP_DEVICE_INTERFACE_DETAIL_DATA DevDetail;
PHIDP_PREPARSED_DATA PreparsedData;
HIDP_CAPS Capabilities;
ULONG Length;
int Index;
BOOL ok;
HANDLE DevHandle;
int DevCount = 0;
vecVidPid.clear();
/* Get GUID for all System HIDs */
HidD_GetHidGuid(&HidGuid);
/* Get Device Information for all present devices */
DevInfo = SetupDiGetClassDevs(&HidGuid,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)
);
DevData.cbSize = sizeof(DevData);
DevDetail = NULL;
Index = -1;
*FIFO_Length = 0;
/* Scan all Devices */
do {
Index++;
/* Device Interface Element of a Device Information set */
ok = SetupDiEnumDeviceInterfaces(DevInfo,
0,
&HidGuid,
Index,
&DevData
);
if (!ok) break;
/* Get Device Interface Details - Get Length */
ok = SetupDiGetDeviceInterfaceDetail(DevInfo,
&DevData,
NULL,
0,
&Length,
NULL
);
/* Allocate memory for Device Detailed Data */
DevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
/* Set cbSize in the DevDetail structure */
DevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
/* Get Device Interface Details */
ok = SetupDiGetDeviceInterfaceDetail(DevInfo,
&DevData,
DevDetail,
Length,
NULL,
NULL
);
if (!ok)
{
free(DevDetail);
DevDetail = NULL;
continue;
}
/* Create File for Device Read/Write */
DevHandle = CreateFile(DevDetail->DevicePath,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
NULL
);
if (DevHandle == INVALID_HANDLE_VALUE)
{
free(DevDetail);
DevDetail = NULL;
continue;
}
DevAttributes.Size = sizeof(DevAttributes);
ok = HidD_GetAttributes(DevHandle, &DevAttributes);
if (!ok)
{
free(DevDetail);
CloseHandle(DevHandle);
DevDetail = NULL;
continue;
}
if (find(vecVidPid.begin(), vecVidPid.end(), _VID_PID_(DevAttributes.VendorID, DevAttributes.ProductID)) == vecVidPid.end())
{
vecVidPid.push_back(_VID_PID_(DevAttributes.VendorID, DevAttributes.ProductID));
free(DevDetail);
CloseHandle(DevHandle);
DevDetail = NULL;
}
} while (DevCount < 20);
SetupDiDestroyDeviceInfoList(DevInfo);
return;
}
void CScannerDlg::OnCbnDropdownComboScanner()
{
// TODO: 在此添加控件通知处理程序代码
unsigned short* a;
a = new unsigned short[100];
memset(a, 0x00, 100);
vecVidPid.clear();
m_combo_scanner.ResetContent();
HID_FindAllDevices(a);
delete a;
int i = 0;
for (auto it = vecVidPid.begin(); it != vecVidPid.end(); it++)
{
CString strTmp;
strTmp.Format(_T("VID:%04x,PID:%04x"), it->V_ID, it->P_ID);
m_combo_scanner.InsertString(i, strTmp);
i++;
}
}
void CScannerDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
CString strTmp;
int nSel = m_combo_scanner.GetCurSel();
if (nSel != -1)
{
strTmp.Format(_T("%04x"), vecVidPid.at(nSel).V_ID);
gParams.SetVID(strTmp);
strTmp.Format(_T("%04x"), vecVidPid.at(nSel).P_ID);
gParams.SetPID(strTmp);
gParams.SaveXml();
}
else
{
gParams.SetVID(_T("FFFF"));
gParams.SetPID(_T("FFFF"));
gParams.SaveXml();
}
CDialogEx::OnOK();
}
窗口展示