Qt中通过Windows消息进行监测串口的热插拔

1. QAbstractNativeEventFilter

对于此类的Qt官方解释为:
The QAbstractNativeEventFilter class provides an interface for receiving native events, such as MSG or XCB event structs. More…
这个抽象事件过滤类提供了一个接收本地事件的接口,类如Windows的MSG或者XCB…
所以,需要我们的类继承此类,并重写虚函数。形如:

class OwnerClass : public QMainWindow, public QAbstractNativeEventFilter{
	......
	bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
	......
}

2.具体实现

#include <Windows.h>
#include <dbt.h>

bool OwnerClass::nativeEventFilter(const QByteArray & eventType, void * message, long * result)
{
	MSG* msg = reinterpret_cast<MSG*>(message);
	int msgType = msg->message;
	if (msgType == WM_DEVICECHANGE) {
		PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)msg->lParam;
		switch (msg->wParam) {
		case DBT_DEVICEARRIVAL:
			if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
				PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb;
				QString port = QString::fromWCharArray(lpdbv->dbcp_name);//插入的串口名
				//emit open(port);//发送串口打开信号
			}
			break;
		case DBT_DEVICEREMOVECOMPLETE:
			if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT) {
				PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb;
				QString port = QString::fromWCharArray(lpdbv->dbcp_name);//拔出的串口名
				//emit close(port);//发送串口关闭信号
			}
			break;
		case DBT_DEVNODES_CHANGED:
			break;
		default:
			break;
		}
	}
	return QWidget::nativeEvent(eventType, message, result);
}

3 注册

在main函数中注册过滤器,形如下图所示:
在这里插入图片描述

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Windows下实现串口,需要通过Windows API来监测串口事件并做出相应处理。下面是一个使用QT实现串口的示例代码: ```c++ #include <QCoreApplication> #include <QtSerialPort/QSerialPort> #include <QObject> #include <QDebug> #include <windows.h> //定义一个继承自QObject的类,用于处理串口事件 class SerialPortWatcher : public QObject { Q_OBJECT public: SerialPortWatcher(QObject *parent = nullptr) : QObject(parent) {} signals: void serialPortAdded(QString portName); //定义串口入信号 void serialPortRemoved(QString portName); //定义串口出信号 public slots: void checkSerialPorts() //检测串口列表 { QStringList currentSerialPortList = getSerialPortList(); //获取当前串口列表 for (int i = 0; i < currentSerialPortList.size(); i++) { if (!m_serialPortList.contains(currentSerialPortList[i])) //如果当前串口列表有新串口 { emit serialPortAdded(currentSerialPortList[i]); //发射串口入信号 } } for (int i = 0; i < m_serialPortList.size(); i++) { if (!currentSerialPortList.contains(m_serialPortList[i])) //如果当前串口列表串口出 { emit serialPortRemoved(m_serialPortList[i]); //发射串口出信号 } } m_serialPortList = currentSerialPortList; //更新串口列表 } private: QStringList getSerialPortList() //获取当前串口列表 { QStringList serialPortList; for (int i = 1; i <= 255; i++) { QString portName = QString("COM%1").arg(i); HANDLE handle = CreateFileA(portName.toStdString().c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (handle != INVALID_HANDLE_VALUE) { CloseHandle(handle); serialPortList.append(portName); } } return serialPortList; } QStringList m_serialPortList; //保存当前串口列表 }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QSerialPort serialPort; SerialPortWatcher *serialPortWatcher = new SerialPortWatcher(&a); //创建串口监测对象 QObject::connect(serialPortWatcher, &SerialPortWatcher::serialPortAdded, [&serialPort](QString portName) { qDebug() << "Serial Port Added: " << portName; if (!serialPort.isOpen()) //如果串口没有打开,就打开新入的串口 { serialPort.setPortName(portName); serialPort.setBaudRate(QSerialPort::Baud115200); serialPort.setParity(QSerialPort::NoParity); serialPort.setDataBits(QSerialPort::Data8); serialPort.setStopBits(QSerialPort::OneStop); if (serialPort.open(QIODevice::ReadWrite)) { qDebug() << "Serial Port Opened: " << portName; } } }); QObject::connect(serialPortWatcher, &SerialPortWatcher::serialPortRemoved, [&serialPort](QString portName) { qDebug() << "Serial Port Removed: " << portName; if (serialPort.isOpen() && serialPort.portName() == portName) //如果串口已经打开,并且是当前出的串口,就关闭串口 { serialPort.close(); qDebug() << "Serial Port Closed: " << portName; } }); QTimer *timer = new QTimer(&a); timer->setInterval(1000); //设置定时器时间间隔为1秒 timer->start(); QObject::connect(timer, &QTimer::timeout, serialPortWatcher, &SerialPortWatcher::checkSerialPorts); //连接定时器与串口监测对象的检测方法 return a.exec(); } #include "main.moc" ``` 上述代码,我们创建了一个继承自QObject的类SerialPortWatcher,通过Windows API获取当前串口列表,并定时检测串口列表的变化,如果有串口入或出,就发射相应的信号。在主函数,我们连接SerialPortWatcher的信号与串口打开和关闭的槽函数,实现自动打开和关闭串口。最后,我们启动事件循环,定时检测串口列表的变化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qingchuu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值