MFC串口热拔插与可用串口自动检测的实现方法

我的未来我决定 提交于 2020-01-10 21:17:14

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控件变量名即可

设置方法如下:
在这里插入图片描述
笔者写的简易串口助手中的实现
在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!