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

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

大家都知道,通过设备管理器我们可以看到可用串口号的列表,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)
	{
		TCHAR		szPortName[256], szComName[256];
		DWORD		dwLong, dwSize;
		int			nCount	= 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();
}
至此,通过注册表的方法便已实现。

源码:通过注册表实现

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现串口热插拔检测,可以使用Qt的QSerialPort类和QSerialPortInfo类。 QSerialPort类用于访问串口,可以通过它打开、关闭、设置串口参数、读取和写入串口数据等。而QSerialPortInfo类则提供了有关系统中可用串口的信息,可以用于检测串口热插拔事件。 以下是一个简单的示例代码,演示如何检测串口热插拔事件: ```cpp #include <QtCore> #include <QtSerialPort> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 枚举当前可用的串口 QList<QSerialPortInfo> serialPorts = QSerialPortInfo::availablePorts(); foreach (const QSerialPortInfo &serialPortInfo, serialPorts) { qDebug() << "Found serial port:" << serialPortInfo.portName(); } // 创建一个QSerialPort对象并打开串口 QSerialPort serialPort; serialPort.setPortName("COM1"); serialPort.setBaudRate(QSerialPort::Baud9600); if (serialPort.open(QIODevice::ReadWrite)) { qDebug() << "Opened serial port:" << serialPort.portName(); } else { qDebug() << "Failed to open serial port:" << serialPort.portName(); } // 监听串口热插拔事件 QSerialPortInfo::availablePortsChanged.connect([]() { QList<QSerialPortInfo> currentSerialPorts = QSerialPortInfo::availablePorts(); qDebug() << "Serial ports changed. Found" << currentSerialPorts.count() << "serial ports."; // 遍历当前可用的串口,判断是否串口被插入或拔出 foreach (const QSerialPortInfo &currentSerialPortInfo, currentSerialPorts) { bool found = false; foreach (const QSerialPortInfo &serialPortInfo, serialPorts) { if (currentSerialPortInfo.portName() == serialPortInfo.portName()) { found = true; break; } } if (!found) { qDebug() << "Serial port" << currentSerialPortInfo.portName() << "was inserted."; } } foreach (const QSerialPortInfo &serialPortInfo, serialPorts) { bool found = false; foreach (const QSerialPortInfo &currentSerialPortInfo, currentSerialPorts) { if (currentSerialPortInfo.portName() == serialPortInfo.portName()) { found = true; break; } } if (!found) { qDebug() << "Serial port" << serialPortInfo.portName() << "was removed."; } } serialPorts = currentSerialPorts; }); return a.exec(); } ``` 上面的代码首先枚举当前可用的串口,并创建一个QSerialPort对象并打开串口。然后监听串口热插拔事件,并在事件发生时输出相关信息。其中,QSerialPortInfo::availablePortsChanged信号在串口热插拔事件发生时会被触发,可以用connect函数将其与一个槽函数连接起来。 需要注意的是,QSerialPortInfo::availablePortsChanged信号在Windows操作系统下并不是实时触发的,而是有一定的延迟。如果需要实现更加实时的热插拔检测,可以考虑使用Qt的winEvent函数或者使用WinAPI函数来实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值