MFC串口热拔插与可用串口自动检测的实现方法
在网上看找了很多关于串口自动检测检测与热拔插的实现,感觉比较麻烦,很多不能直接拿过来用。笔者参考了网上的一些方法,自己写了一个比较简单的实现方式。由于本人水平有些,不足之处请谅解!
主要可分为以下几个部分
1.CSerialportDlg.h中添加以下代码
protected:
//实现串口热插拔
afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData);
afx_msg void RefreshCom(void);
BOOL EnumSerialPort(CStringArray& saCom);
2.CSerialportDlg.c中添加以下代码
主要是对头文件的三个函数声明的代码实现
#include <Dbt.h> //需要在CSerialportDlg.c的头文件中添加此头文件
//否则OnDeviceChange(函数中的宏定义会报错)
BOOL CSerialportDlg::OnDeviceChange(UINT nEventType, DWORD dwData)
{
switch (nEventType)
{
//串口被移除
case DBT_DEVICEREMOVECOMPLETE:
RefreshCom();
break;
//串口插入或者变为有效
case DBT_DEVICEARRIVAL:
RefreshCom();
break;
default:
break;
}
return TRUE;
}
void CSerialportDlg::RefreshCom(void)
{
//m_combox_com 为你定义的COMBOX控件变量名
CStringArray k;
int size = 0;
int index = 0;
m_combox_com.ResetContent(); //清除控件所有内容
for (int i = 1; i < 15; i++) //重新加载
{
CString str;
str.Format(_T("COM%d"), i);
m_combox_com.AddString(str);
}
EnumSerialPort(k);
size = k.GetSize();
for (int i = 0; i < size; i++)
{
CString str = k.GetAt(i);
index = m_combox_com.FindStringExact(0, str);
if (index != CB_ERR)
{
m_combox_com.DeleteString(index);
m_combox_com.InsertString(index, str + "(可用串口)");
}
}
m_combox_com.SetCurSel(index);
}
BOOL CSerialportDlg::EnumSerialPort(CStringArray& saCom)
{
HKEY hKey;
DWORD dwIndex;
LONG lResult;
DWORD dwType;
DWORD dwKeyNameLen;
CHAR szKeyName[256];
DWORD dwKeyDataLen;
UCHAR szKeyData[80];
CString strCom, str;
LPCTSTR lpSubKey;
saCom.RemoveAll();
lpSubKey = _T("HARDWARE\\DEVICEMAP\\SERIALCOMM\\");
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS)
{
str.Format(_T("[Main] RegOpenKeyEx()函数打开失败!"));
AfxMessageBox(str);
return FALSE;
}
dwIndex = 0;
while (1)
{
memset(szKeyName, 0x0, sizeof(szKeyName));
memset(szKeyData, 0x0, sizeof(szKeyData));
dwKeyNameLen = sizeof(szKeyName);
dwKeyDataLen = sizeof(szKeyData);
lResult = RegEnumValue(hKey, dwIndex++, szKeyName, &dwKeyNameLen, NULL, &dwType, szKeyData, &dwKeyDataLen);
if ((lResult == ERROR_SUCCESS) || (lResult == ERROR_MORE_DATA))
{
strCom = (char*)szKeyData;
saCom.Add(strCom);
}
else
{
break;
}
}
RegCloseKey(hKey);
return true;
}
并在消息列表中添加ON_WM_DEVICECHANGE,当有设备插入或者拔出时,便会调用OnDeviceChange()函数
BEGIN_MESSAGE_MAP(CSerialportDlg, CDialogEx)
ON_WM_DEVICECHANGE() //添加设备改变消息
END_MESSAGE_MAP()
在 CSerialportDlg::OnInitDialog()函数中调用一次RefreshCom()函数,使得程序第一次运行时更新一次串口信息
RefreshCom();
注意事项:需要将编译器设置为多字节字符集,否则串口会无法更新!!!只需要将RefreshCom()函数中的m_combox_com 为你定义的串口COMBOX控件变量名即可
设置方法如下:
笔者写的简易串口助手中的实现
来源:CSDN
作者:InspireHH
链接:https://blog.csdn.net/weixin_44580647/article/details/103928467