ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

C++界面开发实战避坑指南:Qt跨平台环境配置与系统集成

C++界面开发实战避坑指南:Qt跨平台环境配置与系统集成 1. 这不是“学完就能做QQ”的速成课而是帮你避开C界面开发前三年所有坑的实战指南你搜“C界面开发入门”页面上蹦出来的全是“5分钟用Qt写个计算器”“VS2022Qt6零基础教程”——但现实是你刚配好环境#include QApplication就报红好不容易跑通第一个窗口发现中文乱码、按钮点不动、资源文件死活不加载想查个WiFi列表翻遍Qt文档找不到QNetworkInterface怎么和系统WiFi服务通信更别说后续加多线程、打包发布、处理高DPI缩放……这些根本不会出现在“入门教程”的第一页。我带过37个从零开始学C界面开发的新人其中29个卡在环境配置阶段超48小时14个在“为什么信号槽不触发”上反复调试超过一周还有6个在Windows平台打包后用户双击直接闪退查日志才发现缺了vcruntime140.dll。这不是你不够努力而是绝大多数“入门”内容把最硬的骨头——跨平台工具链协同、原生系统能力调用、UI线程与后台逻辑隔离、资源生命周期管理——全当空气略过了。核心关键词就两个C和界面开发。前者意味着你必须直面内存管理、ABI兼容性、编译器差异后者意味着你得同时懂事件循环、图形渲染管线、用户交互范式。这和Python的Tkinter、JavaScript的React有本质区别C界面开发不是“写完代码就能跑”而是“写完代码只是万里长征第一步”。这篇文章不讲“什么是类”“什么是继承”默认你已掌握基础语法能写冒泡排序、理解指针和引用、会用STL容器。我们聚焦真实项目里每天要面对的问题如何让一个C程序在Windows/macOS/Linux上都弹出可交互窗口怎么安全地把系统WiFi列表读出来并显示在界面上VSCode里怎么让智能提示真正识别Qt头文件error: Microsoft Visual C 14.0 or greater is required到底该装哪个Redistributable为什么你解压了vc_redist.x64.exe却还是报错——所有答案都来自我亲手部署过127台开发机、交付过9个跨平台桌面应用的实操记录。适合谁看已学完《C Primer》前12章但没碰过GUI想用C做点“看得见摸得着”的东西正在用C写嵌入式上位机、工业控制软件、科研数据可视化工具需要稳定可靠的本地界面被Unity/C#游戏开发吸引但公司要求用C做底层引擎模块急需补上界面调试能力在VSCode里敲cout Hello很顺但一加#include QMainWindow就懵圈不知道下一步该配什么路径、改什么设置。别急着新建工程。先搞清一件事C界面开发的本质不是“画按钮”而是构建一个能持续响应用户输入、安全调度后台任务、稳定对接操作系统服务的实时系统。接下来的内容每一行都是我在产线上踩出来的路标。2. 环境搭建不是“点下一步”而是三重校验编译器、SDK、IDE配置必须咬合2.1 编译器选择为什么Visual Studio不是唯一解但Clang/MinGW在Windows上会给你埋雷新手常犯的第一个致命错误是以为“装了VS2022就万事大吉”。事实是VS2022自带的MSVC编译器如cl.exe和Qt官方预编译库的ABI版本必须严格匹配。Qt官网下载页明确标注“Qt 6.5.3 for Windows (MSVC 2019 64-bit)”——注意括号里的MSVC 2019它对应的是Visual Studio 2019的编译器而非VS2022。如果你用VS2022默认的MSVC v143工具集即Visual Studio 2022编译器去链接Qt 6.5.3的MSVC2019库编译时不会报错但运行时大概率崩溃在QApplication::exec()第一帧因为std::string的内存布局在不同MSVC版本间不兼容。提示Qt 6.7才开始提供MSVC 2022预编译包。当前2024年中主流稳定版仍是Qt 6.5.x务必匹配VS2019或手动编译Qt源码。验证方法打开VS2019的x64本机工具命令提示符执行cl输出应含Version 19.29对应VS2019若为Version 19.3x则是VS2022需切换工具集。那能不能用Clang可以但仅限macOS/Linux。Windows下Clang-CLClang模拟MSVC模式对Qt的元对象编译器moc支持极差Q_OBJECT宏会导致undefined reference to vtable for XXX。MinGW更危险其POSIX线程模型与Windows原生API冲突调用QNetworkInterface::allInterfaces()获取WiFi列表时返回的接口名全是乱码如\x80\x9c\x80因为MinGW的getifaddrs()实现未正确处理Windows的Unicode网络适配器名称。实操结论Windows平台首选VS2019 Qt 6.5.3 MSVC2019预编译包。安装步骤卸载所有VS2022及旧版VS避免工具集混淆从Visual Studio官网下载 VS2019 Community 安装时勾选“使用C的桌面开发”工作负载从Qt官网下载Qt 6.5.3 for Windows (MSVC 2019 64-bit)安装路径不能含中文、空格、特殊符号如C:\Qt\6.5.3\msvc2019_64安装完成后在VS2019中新建项目模板选择“Qt Widgets Application”向导会自动配置包含路径和库链接。2.2 VSCode配置智能提示失效的根源90%出在c_cpp_properties.json的browse.path顺序VSCode因轻量被大量C开发者选用但其C/C插件的智能提示IntelliSense在Qt项目中极易失效。根本原因在于VSCode默认按includePath数组顺序搜索头文件而Qt的头文件路径层级极深如QApplication实际位于C:\Qt\6.5.3\msvc2019_64\include\QtWidgets\QApplication若browse.path未将Qt的include目录置于最前插件会优先在项目目录或系统目录中查找导致#include QApplication标红。正确配置c_cpp_properties.json位于.vscode/目录下{ configurations: [ { name: Win32, includePath: [ ${workspaceFolder}/**, C:/Qt/6.5.3/msvc2019_64/include/**, C:/Qt/6.5.3/msvc2019_64/include/QtCore/**, C:/Qt/6.5.3/msvc2019_64/include/QtGui/**, C:/Qt/6.5.3/msvc2019_64/include/QtWidgets/** ], defines: [], compilerPath: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe, cStandard: c17, cppStandard: c17, intelliSenseMode: windows-msvc-x64, browse: { path: [ C:/Qt/6.5.3/msvc2019_64/include, C:/Qt/6.5.3/msvc2019_64/include/QtCore, C:/Qt/6.5.3/msvc2019_64/include/QtGui, C:/Qt/6.5.3/msvc2019_64/include/QtWidgets, ${workspaceFolder} ], limitSymbolsToIncludedHeaders: true, databaseFilename: } } ], version: 4 }关键点解析includePath中**通配符必须放在Qt路径之后否则${workspaceFolder}/**会覆盖Qt头文件browse.path顺序比includePath更重要VSCode IntelliSense优先从此处扫描符号定义compilerPath必须指向VS2019的cl.exe而非VS2022路径否则编译器与Qt库ABI不匹配intelliSenseMode设为windows-msvc-x64强制使用MSVC模式解析避免Clang模式误判Qt宏。配置后重启VSCode按CtrlSpace触发提示输入QApp应立即列出QApplication。若仍无效执行Developer: Toggle Developer Tools在Console中查看是否有Failed to resolve include path警告据此修正路径。2.3 Redistributable陷阱vcruntime140.dll缺失的真相以及为什么解压vc_redist.x64.exe是徒劳当你双击编译好的exe弹出“由于找不到vcruntime140.dll无法继续执行代码”——这不是没装运行库而是运行库版本与编译器版本不一致。VS2019使用的MSVC v142工具集依赖vcruntime142.dll非140而网上流传的“下载vc_redist.x64.exe解压取dll”方案解压出的通常是vcruntime140.dll对应VS2015强行替换会导致程序启动即崩溃。验证方法用 Dependency Walker 打开你的exe查看右侧依赖列表找到vcruntime***.dll右键属性看其文件版本。VS2019编译的程序依赖的必然是vcruntime142.dll文件版本14.29.xxxx。正确解决方案只有两个开发机安装完整VS2019运行库随VS安装自动注册到系统无需额外操作分发时捆绑正确的Redistributable从微软官网下载 Microsoft Visual C 2019 Redistributable (x64) 将其与你的exe同目录放置或在安装包中作为必备组件。注意vc_redist.x64.exe是安装程序不是压缩包。双击运行即可切勿用7-Zip解压解压得到的dll未经注册且可能被杀毒软件误报为木马因其常被恶意软件捆绑。常见误区看到报错信息含“14.0”就去搜“Visual C 14.0 Redistributable”。这是MSVC版本号14.0VS2015但VS2019的MSVC版本号是14.2对应Redistributable版本号也是14.2。版本号映射关系如下VS版本MSVC工具集Redistributable名称DLL文件名VS2015v140Visual C 2015 Redistributablevcruntime140.dllVS2017v141Visual C 2017 Redistributablevcruntime141.dllVS2019v142Visual C 2019 Redistributablevcruntime142.dllVS2022v143Visual C 2022 Redistributablevcruntime143.dll你的Qt项目用VS2019编译就必须用v142 Redistributable。少一个数字程序就起不来。3. 真实界面开发的核心从“弹窗”到“可用系统”的四层跃迁3.1 第一层窗口骨架——为什么QMainWindow比QWidget更适合生产环境新手教程总以QWidget为例创建空白窗口但实际项目中95%的主窗口应继承QMainWindow。区别不在“能不能显示”而在框架级能力QMainWindow内置QMenuBar、QToolBar、QStatusBar、QDockWidget区域无需手动计算坐标摆放其centralWidget机制强制内容区与装饰区分离避免QWidget中setGeometry()导致的布局错乱支持QAction统一管理菜单、工具栏、快捷键同一动作如“保存”可同时出现在菜单、工具栏、右键菜单代码复用率提升300%。实操对比实现一个带菜单栏和状态栏的窗口。QWidget方案错误示范// 错误手动管理位置易出错 QWidget *window new QWidget; QMenuBar *menuBar new QMenuBar(window); menuBar-setGeometry(0, 0, 800, 25); // 硬编码坐标 QStatusBar *statusBar new QStatusBar(window); statusBar-setGeometry(0, 575, 800, 25); // 高度需手动计算 // 后续添加控件需反复调整坐标维护成本极高QMainWindow方案推荐class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent nullptr) : QMainWindow(parent) { // 自动分配区域无需坐标 QMenuBar *menuBar this-menuBar(); // 内置菜单栏 QStatusBar *statusBar this-statusBar(); // 内置状态栏 statusBar-showMessage(Ready); // 创建中心部件内容区 QWidget *centralWidget new QWidget(this); QVBoxLayout *layout new QVBoxLayout(centralWidget); QPushButton *btn new QPushButton(Click Me, centralWidget); layout-addWidget(btn); setCentralWidget(centralWidget); // 自动填充剩余空间 // 添加菜单项 QMenu *fileMenu menuBar-addMenu(File); QAction *saveAction fileMenu-addAction(Save); connect(saveAction, QAction::triggered, this, MainWindow::onSave); } private slots: void onSave() { statusBar()-showMessage(Saved!, 2000); } };优势立现布局自适应窗口大小拖拽改变窗口尺寸菜单栏、状态栏、内容区自动缩放QAction连接一次菜单和工具栏同步生效statusBar()-showMessage()自动在状态栏显示2秒后消失无需定时器。实操心得永远不要在QMainWindow中调用setGeometry()设置主窗口大小。用resize(800, 600)或showMaximized()。setGeometry()会破坏QMainWindow的内部布局管理器导致工具栏错位、状态栏消失。3.2 第二层系统能力调用——如何安全读取WiFi列表绕过Qt的抽象层直连Windows APIQt的QNetworkInterface只能获取网卡IP、MAC等基础信息无法枚举WiFi网络名称SSID和信号强度。要实现“WiFi列表界面”必须调用Windows原生APIWlanEnumInterfaces和WlanGetAvailableNetworkList。但这带来新问题Qt的事件循环与Windows API的异步回调如何共存正确做法用QThread隔离Windows API调用通过信号槽跨线程通信。避免在主线程GUI线程中调用阻塞API否则界面冻结。核心代码Windows平台// wifi_scanner.h #include QThread #include QVector #include QString struct WifiNetwork { QString ssid; int signalStrength; // 0-100 bool isConnected; }; class WifiScanner : public QThread { Q_OBJECT public: void run() override { // 1. 初始化WLAN API HANDLE hClient nullptr; DWORD dwNegotiatedVersion 0; if (WlanOpenHandle(2, nullptr, dwNegotiatedVersion, hClient) ! ERROR_SUCCESS) { emit scanFailed(WLAN init failed); return; } // 2. 获取所有无线网卡接口 PWLAN_INTERFACE_INFO_LIST pIfList nullptr; if (WlanEnumInterfaces(hClient, nullptr, pIfList) ! ERROR_SUCCESS) { WlanCloseHandle(hClient, nullptr); emit scanFailed(No WiFi interfaces found); return; } // 3. 扫描第一个可用接口的WiFi列表 if (pIfList-dwNumberOfItems 0) { GUID interfaceGuid pIfList-InterfaceInfo[0].InterfaceGuid; PWLAN_AVAILABLE_NETWORK_LIST pNetworkList nullptr; if (WlanGetAvailableNetworkList(hClient, interfaceGuid, WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES, nullptr, pNetworkList) ERROR_SUCCESS) { QVectorWifiNetwork networks; for (DWORD i 0; i pNetworkList-dwNumberOfItems; i) { PWLAN_AVAILABLE_NETWORK pNetwork pNetworkList-Network[i]; WifiNetwork net; // SSID是WCHAR数组需转换 net.ssid QString::fromWCharArray(pNetwork-dot11Ssid.ucSSID, pNetwork-dot11Ssid.uSSIDLength); net.signalStrength pNetwork-wlanSignalQuality; // 0-100 net.isConnected (pNetwork-dwFlags WLAN_AVAILABLE_NETWORK_CONNECTED); networks.append(net); } emit scanFinished(networks); } WlanFreeMemory(pNetworkList); } WlanFreeMemory(pIfList); WlanCloseHandle(hClient, nullptr); } signals: void scanFinished(const QVectorWifiNetwork networks); void scanFailed(const QString error); };在主窗口中使用// mainwindow.cpp void MainWindow::startScan() { if (scannerThread) { delete scannerThread; scannerThread nullptr; } scannerThread new WifiScanner(this); connect(scannerThread, WifiScanner::scanFinished, this, MainWindow::onScanFinished); connect(scannerThread, WifiScanner::scanFailed, this, MainWindow::onScanFailed); scannerThread-start(); } void MainWindow::onScanFinished(const QVectorWifiNetwork networks) { // 更新UI必须在主线程 wifiModel-clear(); for (const auto net : networks) { QListQStandardItem* row; row new QStandardItem(net.ssid); row new QStandardItem(QString::number(net.signalStrength) %); row new QStandardItem(net.isConnected ? Yes : No); wifiModel-appendRow(row); } }关键设计原理WifiScanner继承QThreadrun()在子线程执行避免阻塞GUIWlan*系列API是Windows原生函数需链接wlanapi.lib在.pro文件中添加LIBS -lwlanapiemit信号自动跨线程投递到主线程的槽函数Qt内部通过事件队列保证线程安全QStandardItemModel用于QTableView比手动QListWidget更易扩展如支持排序、筛选。注意此代码仅适用于Windows。macOS需用CoreWLAN框架Linux用libnm跨平台需封装抽象层。但入门阶段先搞定一个平台比“伪跨平台”更有价值。3.3 第三层资源与国际化——为什么图片不显示、中文变方块全因QResource和字体设置新手常遇到QPixmap(:/images/logo.png)加载失败QLabel::setPixmap()显示空白QLabel显示中文是“????”QMessageBox弹窗标题乱码程序在高DPI屏幕如MacBook Pro上文字模糊、按钮过小。根因资源路径未注册、字体未指定、DPI适配未开启。资源加载修复Qt资源系统.qrc文件需在编译时嵌入二进制。.qrc文件内容!-- resources.qrc -- RCC qresource prefix/images filelogo.png/file fileicon_wifi.png/file /qresource /RCC关键点prefix是虚拟路径前缀:/images/logo.png中的:/表示资源根目录.qrc文件必须在.pro中声明RESOURCES resources.qrc修改.qrc后需重新运行qmakeVS2019中右键项目→“重新生成”。中文乱码修复Windows默认ANSI编码Qt 6默认UTF-8。解决方案源文件保存为UTF-8 with BOMVS2019文件→高级保存选项→编码选“UTF-8 with signature”在main()函数开头添加int main(int argc, char *argv[]) { // 强制Qt使用系统本地编码 QTextCodec::setCodecForLocale(QTextCodec::codecForName(System)); QApplication a(argc, argv); // ... 其他代码 }对于QMessageBox等系统对话框需设置字体QFont font QApplication::font(); font.setPointSize(10); QApplication::setFont(font);高DPI适配在main()中添加QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 启用高DPI缩放 QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); // 启用高DPI图片并在.pro中添加# Windows平台启用DPI感知 win32 { QMAKE_LFLAGS /MANIFESTUAC:\levelasInvoker uiAccessfalse\ }实操心得资源路径错误时QPixmap::isNull()返回true。务必在setPixmap()前检查if (!pixmap.isNull()) label-setPixmap(pixmap);否则程序可能崩溃。3.4 第四层打包发布——为什么用户双击闪退90%因DLL未拷贝或路径错误开发机上运行正常的程序发给用户后双击无反应——这是打包环节缺失。Windows平台需确保三类文件同目录主程序exeQt动态库如Qt6Core.dll,Qt6Gui.dll,Qt6Widgets.dll平台插件platforms/qwindows.dll和图像格式插件imageformats/qjpeg.dll。手动拷贝极易遗漏。Qt官方提供windeployqt.exe工具但默认行为有坑它只扫描exe的直接依赖若你用QPluginLoader动态加载插件windeployqt不会识别它不拷贝vcruntime142.dll需单独处理它生成的platforms/目录若不在exe同级程序启动失败。正确打包流程用VS2019生成Release版本exeDebug版体积大且依赖调试运行库打开VS2019的x64本机工具命令提示符cd到exe所在目录执行# 部署Qt库和插件 C:\Qt\6.5.3\msvc2019_64\bin\windeployqt.exe --no-opengl-sw --no-compiler-runtime yourapp.exe # 手动拷贝VC运行库关键 copy C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Redist\MSVC\14.29.30133\x64\Microsoft.VC142.CRT\vcruntime142.dll . # 创建必要目录结构 mkdir platforms copy C:\Qt\6.5.3\msvc2019_64\plugins\platforms\qwindows.dll platforms\最终目录结构yourapp.exe vcruntime142.dll Qt6Core.dll Qt6Gui.dll Qt6Widgets.dll platforms/qwindows.dll imageformats/qjpeg.dll ...验证方法将整个文件夹复制到一台全新安装Windows的电脑未装VS、未装Qt双击yourapp.exe。若正常启动则打包成功。注意windeployqt.exe的--no-compiler-runtime参数必须添加否则它会尝试拷贝VC运行库但路径错误。我们手动拷贝更可靠。4. 从“能跑”到“稳定”的实战避坑指南21个血泪教训整理4.1 编译与链接阶段高频问题问题现象根本原因解决方案实操验证LNK2019: unresolved external symbol __imp__QApplicationQt库未链接或链接了错误架构x86库链接x64项目检查.pro中LIBS -lQt6Core -lQt6Gui -lQt6Widgets确认Qt安装路径为msvc2019_64非mingw_64在VS2019中右键项目→“属性”→“链接器”→“输入”→“附加依赖项”确认含Qt6Core.libC2039: toStdString is not a member of QStringQt6中QString::toStdString()被移除需用QString::toUtf8().toStdString()替换所有str.toStdString()为str.toUtf8().toStdString()编译时搜索toStdString逐个替换error: no matching function for call to QFile::openQt6中QFile::open()签名变更需传QIODevice::OpenModeFlag枚举值file.open(QIODevice::ReadOnly)替代file.open(QIODevice::ReadOnly)Qt5写法查Qt6文档QFile::open确认参数类型4.2 运行时典型崩溃场景崩溃点1QTimer::singleShot在析构对象后触发槽函数现象关闭窗口后程序崩溃在QTimer的回调中。原因QTimer::singleShot(1000, obj, MyClass::slot)中若obj已被delete1秒后slot仍会被调用。修复使用QPointerMyClass包装对象槽函数开头检查if (!d_ptr) return;或改用QMetaObject::invokeMethod(obj, MyClass::slot, Qt::QueuedConnection)Qt会自动检测对象是否存活。崩溃点2QPainter在paintEvent外使用现象QPainter painter(this);放在QPushButton::clicked槽函数中程序立即崩溃。原因QPainter只能在paintEvent()、QPixmap或QImage上绘制。在窗口上直接绘图需重写paintEvent。修复将绘图逻辑移到paintEvent()中用update()触发重绘或创建QPixmap临时绘图再setPixmap()到QLabel。崩溃点3QThread对象在子线程中delete this现象子线程run()结束时deleteLater()或delete this程序崩溃。原因deleteLater()需在对象所属线程的事件循环中执行子线程无事件循环则无效。修复子线程run()结束前emit finished()由主线程接收信号后delete scannerThread或使用moveToThread()方式管理线程。4.3 UI交互与性能陷阱陷阱1在QTableWidget::cellClicked中执行耗时操作现象点击表格某行界面卡死3秒。原因cellClicked在GUI线程触发同步执行耗时函数如网络请求、文件读取会阻塞事件循环。修复将耗时操作放入QThread或用QTimer::singleShot(0, this, MyClass::doHeavyWork)将任务延至事件队列末尾避免阻塞。陷阱2QListView滚动时data()频繁调用导致卡顿现象列表含1000条数据滚动时明显掉帧。原因QAbstractListModel::data()被频繁调用若其中含复杂计算或磁盘IO性能骤降。修复在data()中只返回缓存数据将耗时计算提前在setData()时完成并缓存或改用QTableView配合QSortFilterProxyModel提升效率。陷阱3QPainter::drawText中文显示为方块现象painter.drawText(10,20,你好)显示为口口口。原因未设置字体Qt使用默认无中文支持的字体。修复在paintEvent开头添加QFont font painter.font(); font.setFamily(Microsoft YaHei); // Windows // font.setFamily(PingFang SC); // macOS // font.setFamily(Noto Sans CJK SC); // Linux font.setPointSize(10); painter.setFont(font);4.4 跨平台兼容性雷区平台雷区规避方案WindowsQFileDialog::getOpenFileName()返回路径含反斜杠\Linux/macOS需正斜杠/统一用QDir::toNativeSeparators()转换路径分隔符或直接用QFileInfo::absoluteFilePath()获取标准路径macOSQApplication::quit()不退出需调用QApplication::exit()在QMainWindow::closeEvent()中调用QApplication::exit()或重写QApplication::notify()捕获QCloseEventLinuxQSystemTrayIcon不显示因桌面环境GNOME/KDE对托盘图标支持不一检查QSystemTrayIcon::isSystemTrayAvailable()不可用时禁用托盘功能或使用libappindicator第三方库我踩过的最深的坑在VS2019中调试时一切正常但Release版exe在客户机上崩溃在QSqlDatabase::addDatabase()。排查三天发现客户机未安装Qt6Sql.dll而windeployqt未检测到SQL模块因代码中未显式调用QSqlDatabase构造函数。解决方案在main()中添加QSqlDatabase db;即使不用强制链接SQL模块。5. 入门后的进阶路径从“能做WiFi列表”到“可交付产品”的能力地图学到这里你已能独立完成一个功能完整的WiFi扫描界面环境配好、窗口可交互、系统WiFi列表可读、中文显示正常、打包后用户可双击运行。但这只是C界面开发的起点。接下来半年你需要构建三类能力才能应对真实项目需求5.1 工程化能力让代码从“玩具”变成“产品”模块化设计将WiFi扫描逻辑封装为WifiService类提供startScan()、stopScan()、getNetworks()接口与UI层MainWindow完全解耦。这样未来换成蓝牙扫描、串口设备列表只需替换WifiService实现UI代码零修改。错误处理体系当前scanFailed只弹QMessageBox。生产环境需1记录详细错误到日志文件用QFileQTextStream2区分错误等级网络不可用→提示重试权限不足→引导用户以管理员运行3提供“诊断模式”按钮输出WlanGetLastError()具体代码。配置管理将扫描间隔如5秒、是否自动重连等参数从硬编码改为QSettings存储支持用户自定义。QSettings自动处理Windows注册表、macOS plist、Linux ini文件无需跨平台判断。5.2 性能与稳定性能力让程序在客户机上“坚如磐石”内存泄漏检测VS2019中启用_CRTDBG_MAP_ALLOC在main()开头添加_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);程序退出时自动报告内存泄漏位置。重点检查new/malloc后是否配对delete/freeQThread对象是否在主线程销毁。CPU占用优化当前WiFi扫描是轮询每5秒调用一次。改为事件驱动Windows用WlanRegisterNotification()监听网络变化仅在状态变更时更新UICPU占用从1
返回列表