news 2026/4/16 14:48:28

Qt 调用 DLL 实现固件升级进度弹窗(完整实战案例)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Qt 调用 DLL 实现固件升级进度弹窗(完整实战案例)

在工业软件、设备配置工具或上位机系统中,**固件升级(Firmware Upgrade)**是一个非常常见但又容易出问题的功能点。
典型需求包括:

  • 调用厂商提供的 Windows DLL 执行升级
  • 升级过程不能阻塞 UI
  • 实时显示升级进度
  • 升级过程中禁止用户误操作
  • 升级完成后给出明确反馈

本文通过一个真实工程级示例,完整讲解如何使用Qt + Windows DLL实现一个可靠的固件升级进度弹窗


一、应用场景说明(为什么要这样做)

在实际项目中,固件升级逻辑通常由硬件厂商提供的 DLL完成,例如:

  • LVDS / V-by-One 显示控制器
  • FPGA / MCU 配置工具
  • 工控采集设备
  • 显示驱动板卡升级程序

Qt 作为上位机 UI 层,只负责:

  • 加载 DLL
  • 调用升级接口
  • 显示升级状态
  • 控制用户交互

升级过程本身必须在后台线程执行,否则 UI 会卡死。


二、设计思路概览

整体架构如下:

  1. 使用LoadLibrary / GetProcAddress动态加载 DLL
  2. 在后台线程中调用升级函数
  3. 通过定时器轮询 DLL 中的升级进度接口
  4. 使用QDialog + QProgressBar显示进度
  5. 升级完成后释放 DLL 并允许用户关闭窗口

这是工业软件中最常见、最稳定的一种升级实现方式


三、DLL 接口定义说明

假设厂商 DLL 中提供如下接口:

// 启动固件升级voidUploadProgram(constchar*filePath);// 查询升级进度(0 ~ 100)intGetUploadProgramSchedule();

Qt 端通过函数指针方式调用。


四、核心实现代码(完整案例)

1. 函数整体结构

voidLVDSVbyOneSignalCollector::firmwareUpInformationBox(QString path)

该函数的职责是:

  • 弹出升级对话框
  • 启动固件升级
  • 显示升级进度
  • 等待升级完成

2. 动态加载 DLL

HMODULE hDll=LoadLibraryA("LVDSVbyOneSignalCollectorDLL.dll");if(!hDll){return;}autopUploadProgram=(PFN_UploadProgram)GetProcAddress(hDll,"UploadProgram");autopGetUploadProgramSchedule=(PFN_GetUploadProgramSchedule)GetProcAddress(hDll,"GetUploadProgramSchedule");if(!pUploadProgram||!pGetUploadProgramSchedule){FreeLibrary(hDll);return;}

为什么使用动态加载?

  • DLL 由第三方提供
  • 可选功能模块
  • 避免启动时强依赖
  • 方便版本替换

3. 构建升级 UI(不可中断)

QDialog*dialog=newQDialog(nullptr);dialog->setWindowTitle(tr("Firmware Upgrade"));dialog->setWindowModality(Qt::ApplicationModal);dialog->setFixedSize(360,140);// 禁止右上角关闭dialog->setWindowFlags(dialog->windowFlags()&~Qt::WindowCloseButtonHint);

这是一个应用级模态窗口,升级过程中用户无法操作主界面。


4. UI 元素布局

QLabel*label=newQLabel(tr("Upgrading firmware, please wait..."),dialog);QProgressBar*progressBar=newQProgressBar(dialog);progressBar->setRange(0,100);progressBar->setValue(0);QPushButton*btnOk=newQPushButton(tr("OK"),dialog);btnOk->setEnabled(false);

升级未完成前,OK 按钮不可点击,避免误关闭。


5. 后台线程执行升级(关键)

QFuture<void>future=QtConcurrent::run([=](){pUploadProgram(rInfor.filePath);});

这里使用QtConcurrent::run的目的非常明确:

  • 避免 UI 阻塞
  • 升级逻辑与界面解耦
  • 不需要手写 QThread

这是 Qt 工程中推荐的做法之一


6. 使用 QTimer 轮询升级进度

QTimer*timer=newQTimer(dialog);QObject::connect(timer,&QTimer::timeout,dialog,[=](){intvalue=pGetUploadProgramSchedule();// 0~100progressBar->setValue(value);if(future.isFinished()){timer->stop();progressBar->setValue(100);label->setText(tr("Firmware upgrade completed."));btnOk->setEnabled(true);FreeLibrary(hDll);}});timer->start(300);

这种设计的优点:

  • 不需要 DLL 回调
  • 逻辑简单、稳定
  • 工业项目中极其常见

7. 升级完成后退出

QObject::connect(btnOk,&QPushButton::clicked,dialog,[=](){dialog->accept();dialog->deleteLater();});

只有在升级完成后,用户才能关闭窗口。


五、工程级注意事项(非常重要)

1️⃣ 文件路径生命周期问题

std::string str=path.toStdString();rInfor.filePath=str.c_str();

如果 DLL 在内部异步使用该指针,这里存在风险。
更安全的方式是保证字符串长期有效(如成员变量或深拷贝)。


2️⃣ DLL 卸载时机

FreeLibrary必须确保:

  • 升级线程完全结束
  • DLL 内部没有残留线程

否则可能导致随机崩溃。


3️⃣ 建议增加失败与超时处理

生产环境中建议补充:

  • 升级失败状态
  • 超时检测
  • 错误码提示
  • 日志记录

六、总结

本文通过一个真实工业项目中的固件升级案例,展示了:

  • Qt 如何调用 Windows DLL
  • 如何在后台线程执行耗时任务
  • 如何安全地显示升级进度
  • 如何设计不可中断的升级 UI

这种结构在工业上位机 / 设备工具 / 显示控制软件中非常通用,具有很高的工程参考价值。


voidLVDSVbyOneSignalCollector::firmwareUp(){QMessageBox msgBox;msgBox.setWindowTitle("提示");msgBox.setText("你确定要继续吗?");msgBox.setIcon(QMessageBox::Question);msgBox.setStandardButtons(QMessageBox::Ok|QMessageBox::Cancel);msgBox.button(QMessageBox::Ok)->setText("更新");msgBox.button(QMessageBox::Cancel)->setText("取消");intret=msgBox.exec();if(ret==QMessageBox::Ok){qDebug()<<"用户点击了确定按钮";QString path=ui.lineEdit_bootPath->text();QFileInfofileInfo(path);if(fileInfo.exists()){if(fileInfo.isDir()){qDebug()<<"路径是有效的目录";}elseif(fileInfo.isFile()){qDebug()<<"路径是有效的文件";}}else{qDebug()<<"路径无效";QMessageBox::information(this,"path",QString("The path is invalid."));return;}firmwareUpInformationBox(path);}elseif(ret==QMessageBox::Cancel){qDebug()<<"用户点击了关闭按钮";}}voidLVDSVbyOneSignalCollector::firmwareUpInformationBox(QString path){HMODULE hDll=LoadLibraryA("LVDSVbyOneSignalCollectorDLL.dll");if(!hDll){return;}PFN_UploadProgram pUploadProgram=(PFN_UploadProgram)GetProcAddress(hDll,"UploadProgram");PFN_GetUploadProgramSchedule pGetUploadProgramSchedule=(PFN_GetUploadProgramSchedule)GetProcAddress(hDll,"GetUploadProgramSchedule");if(!pUploadProgram||!pGetUploadProgramSchedule){FreeLibrary(hDll);return;}std::string str=path.toStdString();rInfor.filePath=str.c_str();/* ================== UI ================== */QDialog*dialog=newQDialog(nullptr);dialog->setWindowTitle(tr("Firmware Upgrade"));dialog->setWindowModality(Qt::ApplicationModal);dialog->setFixedSize(360,140);// 禁止关闭dialog->setWindowFlags(dialog->windowFlags()&~Qt::WindowCloseButtonHint);QLabel*label=newQLabel(tr("Upgrading firmware, please wait..."),dialog);QProgressBar*progressBar=newQProgressBar(dialog);progressBar->setRange(0,100);progressBar->setValue(0);QPushButton*btnOk=newQPushButton(tr("OK"),dialog);btnOk->setEnabled(false);// 完成前不可点击QVBoxLayout*layout=newQVBoxLayout(dialog);layout->addWidget(label);layout->addWidget(progressBar);layout->addWidget(btnOk,0,Qt::AlignRight);dialog->setLayout(layout);dialog->show();/* ================== 后台线程 ================== */QFuture<void>future=QtConcurrent::run([=](){pUploadProgram(rInfor.filePath);});/* ================== 进度轮询 ================== */QTimer*timer=newQTimer(dialog);QObject::connect(timer,&QTimer::timeout,dialog,[=](){intvalue=pGetUploadProgramSchedule();// 0~100progressBar->setValue(value);if(future.isFinished()){timer->stop();progressBar->setValue(100);label->setText(tr("Firmware upgrade completed."));btnOk->setEnabled(true);FreeLibrary(hDll);}});timer->start(300);/* ================== 完成后退出 ================== */QObject::connect(btnOk,&QPushButton::clicked,dialog,[=](){dialog->accept();dialog->deleteLater();});}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 10:20:43

游泳池专用涂料施工哪种好?资深分析师带你避坑选材

行业痛点分析 游泳池涂料哪种好一直是行业难题。传统涂料易脱落开裂。水质化学物质侵蚀严重。维护成本居高不下。施工周期长影响运营。用户普遍反映返修率高。每年维修费用惊人。数据显示游泳池涂料哪种好的问题困扰着62%的运营方。实测发现普通涂料使用寿命仅2-3年。频繁翻新造…

作者头像 李华
网站建设 2026/4/16 10:20:40

为什么顶尖团队都在抢装Open-AutoGLM?真相令人震惊

第一章&#xff1a;安装Open-AutoGLM推理引擎框架Open-AutoGLM 是一个面向自动化代码生成与自然语言推理的高性能深度学习推理引擎&#xff0c;支持多种大语言模型的本地化部署与高效推理。该框架基于 PyTorch 构建&#xff0c;具备低延迟、高并发和模块化设计等优势&#xff0…

作者头像 李华
网站建设 2026/4/16 10:21:13

Python+Vue的 课程实验教学项目管理系统Pycharm django flask

这里写目录标题 项目介绍项目展示详细视频演示感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff08;免费咨询指导选题&#xff09;&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;希望帮助更多的人技术栈文章下方名片联系我即可~解决的思…

作者头像 李华
网站建设 2026/4/16 10:22:15

waic Open-AutoGLM究竟强在哪:3个关键突破+2个真实落地案例

第一章&#xff1a;waic Open-AutoGLM究竟强在哪 waic Open-AutoGLM 是一款面向自动化自然语言处理任务的开源大模型框架&#xff0c;凭借其高度模块化设计与对 GLM 架构的深度优化&#xff0c;在多场景下展现出卓越性能。该框架不仅支持零样本迁移与小样本学习&#xff0c;还集…

作者头像 李华
网站建设 2026/4/16 10:20:22

怎么实现智能供应链协同以降低库存成本?

在当今全球供应链动荡加剧、绿色转型加速、技术迭代提速的背景下&#xff0c;传统线性、割裂的供应链管理模式已难以为继。信息孤岛、响应滞后、质量追溯困难、碳足迹难以计量等问题&#xff0c;正倒逼企业迈向一种全新的协作范式——智能供应链协同。这不仅是技术的升级&#…

作者头像 李华
网站建设 2026/4/16 5:06:14

基于PLC的可编程自动喂料车:S7 - 200与组态王的奇妙结合

No.375 S7-200 组态王 基于PLC的可编程自动喂料车在工业自动化领域&#xff0c;基于PLC&#xff08;可编程逻辑控制器&#xff09;的设备控制方案越来越普及。今天咱们来聊聊编号为No.375的基于PLC的可编程自动喂料车项目&#xff0c;这里面用到了西门子S7 - 200系列PLC以及组态…

作者头像 李华