QT--实现串口热拔插

提示:本文为学习记录,若有疑问,请联系作者,谦虚受教


前言

通过继承QAbstractNativeEventFilter接口实现串口热插拔监测功能;
通过在QWidget中重写nativeEvent实现串口热插拔监测功能;
通过一个函数获取系统中所有可用串口名;
自动添加、移除可用串口。


一、.H文件

代码如下(示例):

#ifndef COMCHANGE_H
#define COMCHANGE_H

#include <QObject>
#include <qabstractnativeeventfilter.h>
#include <windows.h>
#include "dbt.h"

class ComChange : public QObject, public QAbstractNativeEventFilter
{
    Q_OBJECT
public:
    static ComChange* getInstance();
    static QStringList getAvailablePort();
    void setHWND(HWND hwnd);

private:
    explicit ComChange(QObject *parent = nullptr);

protected:
    bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);

signals:
    /**
     * @brief       传出串口热插拔状态
     * @param name  串口名
     * @param flag  true:插入 false:拔出
     */
    void comStatus(QString name, bool flag);

private:
    static ComChange* m_comChange;
    HWND m_hwnd;

};

#endif // COMCHANGE_H


二、.CPP

#include "comchange.h"
#include <QApplication>
#include <QMutex>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <qdebug.h>


ComChange* ComChange::m_comChange = nullptr;
ComChange *ComChange::getInstance()
{
    if(m_comChange == nullptr)
    {
        static QMutex mutex;         //实例互斥锁。
        QMutexLocker locker(&mutex); //加互斥锁。
        if(m_comChange == nullptr)
        {
            m_comChange = new ComChange();
        }
    }
    return m_comChange;

}

/**
 * @brief   获取系统中所有可用的串口名
 * @return
 */
QStringList ComChange::getAvailablePort()
{
    QStringList strName;
    foreach(const QSerialPortInfo& info, QSerialPortInfo::availablePorts())
    {
        QSerialPort port(info);
        if(port.open(QIODevice::ReadWrite))
        {
            strName << info.portName();
            port.close();
        }
    }
    return strName;
}

/**
 * @brief       设置窗口句柄用于过滤事件
 * @param hwnd
 */
void ComChange::setHWND(HWND hwnd)
{
    this->m_hwnd = hwnd;
}

ComChange::ComChange(QObject *parent) : QObject(parent)
{
    qApp->installNativeEventFilter(this);        // 安装事件过滤器
}

bool ComChange::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
    MSG* msg = reinterpret_cast<MSG*>(message);
    if(msg->message == WM_DEVICECHANGE               // 通知应用程序设备或计算机的硬件配置发生更改。
      && msg->hwnd == this->m_hwnd)                  // 过滤事件
    {
        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 strName = QString::fromWCharArray(lpdbv->dbcp_name);  //插入的串口名
                emit comStatus(strName, true);
            }
            break;
        }
        case DBT_DEVICEREMOVECOMPLETE:      // 拔出
        {
            if (lpdb->dbch_devicetype == DBT_DEVTYP_PORT)           // 设备类型为串口
            {
                PDEV_BROADCAST_PORT lpdbv = (PDEV_BROADCAST_PORT)lpdb;
                QString strName = QString::fromWCharArray(lpdbv->dbcp_name);  //拔出的串口名
                emit comStatus(strName, false);
            }
            break;
        }
        default:
            break;
        }
    }

    return false;
}



三、运用

ComChange::getInstance()->setHWND(HWND)this->winId());
connect(ComChange::getInstance(),&ComChange::sig_comStatus,this,&MainWindow::Slt_comStatus);
ui.CB_COM->addItems(ComChange::getAvailablePort());

总结

善于总结,多进一步。

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值