【38】MFC入门到精通——MFC 2种方法实现自动查找串口号 Combobox 控件

文章目录

  • [1 添加 Combobox 控件](#1 添加 Combobox 控件)
  • [2 添加控件变量 m_combobox1](#2 添加控件变量 m_combobox1)
  • [3.头文件 添加两个函数声明](#3.头文件 添加两个函数声明)
  • [4. 实现函数 (两种方法实现 自动查找串口号)](#4. 实现函数 (两种方法实现 自动查找串口号))
  • [5 调用 及运行结果](#5 调用 及运行结果)

1 添加 Combobox 控件

2 添加控件变量 m_combobox1

在Combobox 控件右键添加 控件变量 m_combobox1;

添加成功后,可以看到以下两个地方多了两行代码;

cpp 复制代码
CComboBox m_combobox1;
cpp 复制代码
DDX_Control(pDX, IDC_COMBO2, m_combobox1);

3.头文件 添加两个函数声明

cpp 复制代码
	BOOL GetComPort2(int FindComNum);
	BOOL GetComPort();

4. 实现函数 (两种方法实现 自动查找串口号)

以下两个 GetComPort函数,任意一个都可以

cpp 复制代码
BOOL CMFCApplication1Dlg::GetComPort()
{
	long lReg;
	HKEY hKey;
	DWORD MaxValueLength;
	DWORD dwValueNumber;
	lReg = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
		0, KEY_QUERY_VALUE, &hKey);
	if (lReg != ERROR_SUCCESS) //成功时返回ERROR_SUCCESS,
	{
		AfxMessageBox(TEXT("Open Registry Error!\n"));
		return FALSE;
	}

	lReg = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
		&dwValueNumber, &MaxValueLength, NULL, NULL, NULL);

	if (lReg != ERROR_SUCCESS) //没有成功
	{
		AfxMessageBox(TEXT("Getting Info Error!\n"));
		return FALSE;
	}

	TCHAR* pValueName, * pCOMNumber;
	DWORD cchValueName, dwValueSize = 10;

	for (int i = 0; i < dwValueNumber; i++)
	{
		cchValueName = MaxValueLength + 1;
		dwValueSize = 10;
		pValueName = (TCHAR*)VirtualAlloc(NULL, cchValueName, MEM_COMMIT, PAGE_READWRITE);
		lReg = RegEnumValue(hKey, i, pValueName,
			&cchValueName, NULL, NULL, NULL, NULL);

		if ((lReg != ERROR_SUCCESS) && (lReg != ERROR_NO_MORE_ITEMS))
		{
			AfxMessageBox(TEXT("Enum Registry Error or No More Items!\n"));
			return FALSE;
		}

		pCOMNumber = (TCHAR*)VirtualAlloc(NULL, 6, MEM_COMMIT, PAGE_READWRITE);
		lReg = RegQueryValueEx(hKey, pValueName, NULL,
			NULL, (LPBYTE)pCOMNumber, &dwValueSize);

		if (lReg != ERROR_SUCCESS)
		{
			AfxMessageBox(TEXT("Can not get the name of the port"));
			return FALSE;
		}

		CString str(pCOMNumber);
		m_combobox1.AddString(str); //把获取的值加入到ComBox控件中
		m_combobox1.SelectString(0, str);// 把获取的串口,给combobox的控件选择第一个串口号
		//m_combobox1.SetCurSel(0);//让combo box的control控件选择第一个串口号(第一个不一定是获取到的那个)

		VirtualFree(pValueName, 0, MEM_RELEASE);
		VirtualFree(pCOMNumber, 0, MEM_RELEASE);
	}

	return TRUE;
}

两个 GetComPort函数,任意一个都可以

cpp 复制代码
/*查找串口号,FindComNum=0,从COM 1~16 搜索,非0时,判断其是否存在*/
BOOL CMFCApplication1Dlg::GetComPort2(int FindComNum)
{
	CString comPortStr;
	CString comStr;
	int iTmp;
	int jTmp;
	//m_com = 0;
	int kTmp = 0;
	HANDLE m_hCom;

	if (FindComNum == 0) // 如果串口存在,则执行相应的初始化(采用控件)
	{
		jTmp = 1;
		iTmp = 16;
		comPortStr.Empty();//清除


		for (; jTmp <= iTmp; jTmp++)
		{
			if (jTmp < 10)
			{
				comStr.Format(_T("COM%d"), jTmp);
			}
			else
			{
				comStr.Format(_T("\\\\.\\COM%d"), jTmp);//大于10就要改变输入方式,否则找不到
			}
			m_hCom = CreateFile(comStr, GENERIC_READ |
				GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
				FILE_FLAG_OVERLAPPED, NULL);  // 这里的CreateFile函数起了很大的作用,可以用来创建系统设备文件,如果该设备不存在或者被占用,则会返回一个错误,
												//即下面的 INVALID_HANDLE_VALUE ,据此可以判断可使用性。详细参见MSDN中的介绍。
			if (m_hCom != INVALID_HANDLE_VALUE) // 如果没有该设备,或者被其他应用程序在用    
			{
				/*查找可用串口*/
				comStr.Format(_T("COM%d"), jTmp);
				comPortStr += comStr;    //全局记录字符串,edit用于显示
				comPortStr += "  ";
				kTmp++;
				if (kTmp % 8 == 0)
					comPortStr += "\r\n    ";
				m_combobox1.AddString(comStr);
				if (kTmp == 1)
					m_combobox1.SelectString(0, comStr);// 把获取的串口,给combobox的控件选择第一个串口号
					//m_combobox1.SetCurSel(0);//让combo box的control控件选择第一个串口号(第一个不一定是获取到的那个)
			}

			SetCommMask(m_hCom, 0);// 关闭文件句柄,后面我们采用控件,不用API
			CloseHandle(m_hCom);
		}
		if (jTmp)
			return TRUE;
		else
			return FALSE;
	}
	else
	{
		if (FindComNum < 10)
		{
			comStr.Format(_T("COM%d"), FindComNum);
		}
		else
		{
			comStr.Format(_T("\\\\.\\COM%d"), FindComNum);//大于10就要改变输入方式,否则找不到
		}
		m_hCom = CreateFile(comStr, GENERIC_READ |
			GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
			FILE_FLAG_OVERLAPPED, NULL);  // 这里的CreateFile函数起了很大的作用,可以用来创建系统设备文件,如果该设备不存在或者被占用,则会返回一个错误,
											//即下面的 INVALID_HANDLE_VALUE ,据此可以判断可使用性。详细参见MSDN中的介绍。
		if (m_hCom != INVALID_HANDLE_VALUE) // 如果没有该设备,或者被其他应用程序在用
		{
			return FALSE;
		}
		else
		{
			SetCommMask(m_hCom, 0);// 关闭文件句柄,后面我们采用控件,不用API
			CloseHandle(m_hCom);
		}
	}
	return TRUE;
}

void CMFCApplication1Dlg::OnBnClickedButton5()
{
	// TODO: 在此添加控件通知处理程序代码
	GetComPort2(0);
	//GetComPort();
}

5 调用 及运行结果

本人的计算机当前串口COM5 和两个虚拟串口COM1和COM2

在按键里面 调用函数,也可以写在OnInitDialog();里

cpp 复制代码
void CMFCApplication1Dlg::OnBnClickedButton5()
{
	// TODO: 在此添加控件通知处理程序代码
	GetComPort2(0);
	//GetComPort();
}

运行结果

可以看到三个串口都自动检测到了

Visual studio C++ MFC应用程序自动探测串口号

【MFC串口】MFC实现自动查找串口号

相关推荐
AA陈超2 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 P06-14 属性菜单 - 文本值行
c++·游戏·ue5·游戏引擎·虚幻
云知谷2 小时前
【经典书籍】C++ Primer 第15章类虚函数与多态 “友元、异常和其他高级特性” 精华讲解
c语言·开发语言·c++·软件工程·团队开发
weixin_582985183 小时前
OpenCV cv::Mat.type() 以及类型数据转换
c++·opencv·计算机视觉
oioihoii5 小时前
深入理解 C++ 现代类型推导:从 auto 到 decltype 与完美转发
java·开发语言·c++
报错小能手5 小时前
项目——基于C/S架构的预约系统平台 (1)
开发语言·c++·笔记·学习·架构
lingran__5 小时前
算法沉淀第十天(牛客2025秋季算法编程训练联赛2-基础组 和 奇怪的电梯)
c++·算法
oioihoii7 小时前
当无符号与有符号整数相遇:C++中的隐式类型转换陷阱
java·开发语言·c++
Yupureki7 小时前
从零开始的C++学习生活 13:红黑树全面解析
c语言·数据结构·c++·学习·visual studio
2401_876221347 小时前
Euler
c++·数学·算法
赵杰伦cpp9 小时前
C++的继承机制精讲
java·开发语言·c++·后端