VC++ 动态检测串口的热插拔(二)通过注册表实现

时间:2022-06-01 17:57:41

在上一篇文章中讲述了如何通过循环遍历的方法获取可用串口,可是这样的方法过于暴力,难免会想有没有其他的办法那,嘿嘿,那是肯定会有的,不管什么问题,解决问题的方法永远都不止一种。下面讲述如何通过注册表来获取可用串口。

大家都知道,通过设备管理器我们可以看到可用串口号的列表,windows肯定有自己管理各种设备的方法,那就是大家所熟悉的注册表,注册表中记录各种设备信息以及其他重要信息。在HKEY_LOCAL_MACHINE下逐级展开到Hardware\\DeviceMap\\SerialComm,这里记录的就是串口信息。只要通过简单的注册表读取操作我们就可以得到串口列表。

这里将展示给大家,通过注册表读取,并将结果展示到列表框中的例子。

1遍历串口源码如下:

OnInitDialog中如下:

BOOL CDetectComDlg::OnInitDialog()
{
CDialog::OnInitDialog();

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE);// 设置大图标
SetIcon(m_hIcon, FALSE);// 设置小图标

DWORD sStyle = m_ListShow.GetExtendedStyle();
sStyle |= LVS_EX_GRIDLINES;
sStyle |= LVS_EX_FULLROWSELECT;
m_ListShow.SetExtendedStyle(sStyle);
m_ListShow.InsertColumn(0,_T("索引"),LVCFMT_LEFT,100);
m_ListShow.InsertColumn(1,_T("串口号"),LVCFMT_LEFT,100);
TraversalCom();
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}

TraversalCom()函数如下:

void CDetectComDlg::TraversalCom()
{
HKEY hKey;

if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Hardware\\DeviceMap\\SerialComm"), NULL, KEY_READ, &hKey)==ERROR_SUCCESS)
{
TCHARszPortName[256], szComName[256];
DWORDdwLong, dwSize;
intnCount= 0;
while(true)
{
dwLong= dwSize= 256;
if(RegEnumValue(hKey, nCount, szPortName, &dwLong, NULL, NULL, (PUCHAR)szComName, &dwSize)==ERROR_NO_MORE_ITEMS)
break;
CString str;
str.Format("%d",nCount);
m_ListShow.InsertItem(nCount,str);
str.Format(_T("%s "),szComName);
m_ListShow.SetItemText(nCount,1,str);
nCount++;
}
RegCloseKey(hKey);

}
}

这时再刚登陆窗口时便可罗列出可用串口。

2.检测串口的热插拔

这里主要利用Cwnd的ON_WM_DEVICECHANGE消息来处理。
ON_WM_DEVICECHANGE消息在VS是通过手动添加的

注意:此消息只有顶层窗口可以捕获到
因此,首先得手动添加ON_WM_DEVICECHANGE消息:
第一步:在消息映射BEGIN_MESSAGE_MAP(Ctbox_debug_viewDlg, CDialogEx)中添加:

afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData);

第二步:在cpp文件中添加函数声明
afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData);
第三步:实现

BOOL CDetectComDlg::OnDeviceChange(UINT nEventType,DWORD dwData)
{
//DEV_BROADCAST_DEVICEINTERFACE* dbd = (DEV_BROADCAST_DEVICEINTERFACE*) dwData;
switch (nEventType)
{
case DBT_DEVICEREMOVECOMPLETE://移除设备
case DBT_DEVICEARRIVAL://添加设备
ReDetectCom();//刷新列表框的内容
break;

default:
break;
}
return TRUE;
}

RefreshCom的内容

void CDetectComDlg::RefreshCom(void)
{
m_ListShow.DeleteAllItems();
TraversalCom();
}
至此,通过注册表的方法便已实现。

源码:通过注册表实现