【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实现自动查找串口号

相关推荐
咕咕嘎嘎10247 小时前
C++六个默认成员函数
c++
亭上秋和景清9 小时前
指针进阶:函数指针详解
开发语言·c++·算法
胡萝卜3.09 小时前
C++现代模板编程核心技术精解:从类型分类、引用折叠、完美转发的内在原理,到可变模板参数的基本语法、包扩展机制及emplace接口的底层实现
开发语言·c++·人工智能·机器学习·完美转发·引用折叠·可变模板参数
9ilk9 小时前
【C++】--- C++11
开发语言·c++·笔记·后端
FMRbpm9 小时前
队列练习--------最近的请求次数(LeetCode 933)
数据结构·c++·leetcode·新手入门
biter down9 小时前
C++ 函数重载:从概念到编译原理
开发语言·c++
ZouZou老师10 小时前
C++设计模式之解释器模式:以家具生产为例
c++·设计模式·解释器模式
无限进步_11 小时前
深入理解 C/C++ 内存管理:从内存布局到动态分配
c语言·c++·windows·git·算法·github·visual studio
JANGHIGH11 小时前
c++ 多线程(三)
开发语言·c++
点云SLAM11 小时前
C++ 中traits 类模板(type traits / customization traits)设计技术深度详解
c++·算法·c++模板·c++高级应用·traits 类模板·c++17、20·c++元信息