MFC程序中使用QT开发界面

article/2025/9/7 17:43:23

如果你有一个现成的MFC项目在做维护,但是你厌倦了使用MFC繁琐的操作来做界面美化,或者你需要在这个项目中用到QT里面好用的某些功能;亦或者是你需要使用某些只能在MFC中使用的组件,但是界面这部分已经用QT做好了。那么这篇文章可能可以帮助到你

演示环境使用Visual Studio 2019 + QT5.12.8 版本

添加QT依赖

首先创建一个基于对话框的MFC工程,当然其他的像是多文档、单文档工程也是可以的,只是为了简单起见我这里用的是对话框
然后通过鼠标右键点击项目,然后依次点击属性 --> C/C++ -->常规在工程的附加头文件中添加上QCore、QGui、QWidget和QT的头文件路径


这里记得按照对应编译选项来选择包含64位或者32。
接着在连接器–>常规 中的附加库目录中添加qt的lib库

在这里插入图片描述

最后再在连接器–>输入中添加依赖的lib文件,需要注意的是,debug版本需要链接上带d的lib文件,release则链接上不带d的。
在这里插入图片描述
先编译一下,如果没有问题,qt相关的配置已经完成了

添加信号槽机制

MFC是基于Windows 消息队列来处理和响应ui事件的,而qt是采用信号槽机制来响应的,我们虽然添加了qt的依赖,但是现在只能使用其他的qt库,无法使用qt中的信号槽,需要额外添加一些组件来使mfc支持信号槽。

好在这部分需求qt相关的研发人员已经考虑到了,可以在github中找到 QMfcApp
我们可以将这两个文件给拷贝下来,添加到项目中。并且在cpp文件相应位置添加上 #include "pch.h"包含预处理头

中间会有报错,这是因为在Unicode 字符集下 CString 中的字符串类型是 wchar_t* QString::fromLocal8bit 无法 从 wchar_t* 转化为 char* 所以这里可以修改一下,使用 QString::fromStdWString(),然后进行编译

在QMfcApp.cpp的注释里面可以看到,如何使用它

/*!Creates an instance of QApplication, passing the command line of\a mfcApp to the QApplication constructor, and returns the newobject. The returned object must be destroyed by the caller.Use this static function if you want to perform additionalinitializations after creating the application object, or if youwant to create Qt GUI elements in the InitInstance()reimplementation of CWinApp:\codeBOOL MyMfcApp::InitInstance(){// standard MFC initialization// ...// This sets the global qApp pointerQMfcApp::instance(this);// Qt GUI initialization}BOOL MyMfcApp::Run(){int result = QMfcApp::run(this);delete qApp;return result;}\endcode\sa run()
*/

首先在app类的InitInstance 函数中初始化QApplication类

BOOL CMFCWithQtApp::InitInstance()
{CWinApp::InitInstance();QMfcApp::instance(this);return true;
}

然后需要重写 app类的run 方法,在该方法中调用QMFC 的run方法

int CMFCWithQtApp::Run()
{int result = QMfcApp::run(this);delete qApp;return result;
}

再次编译一下,完成了往mfc中添加信号槽机制的功能

添加qt界面

在项目中新建一个界面类,让他继承自QWidget,如下

// MainUI.h
#pragma once
#include <QWidget>class MainUI: public QWidget
{Q_OBJECT
public:MainUI(QWidget* parent = nullptr);~MainUI();
};//MainUI.cpp
#include "pch.h"
#include "MainUI.h"
#include <QPushButton>MainUI::MainUI(QWidget* parent) :QWidget(parent)
{setWindowTitle("Qt Windows");setFixedSize(800, 720);QPushButton* pBtn = new QPushButton(QString::fromLocal8Bit("这是一个Qt按钮"), this);
}MainUI::~MainUI()
{}

然后在App 类的 InitInstance 中启动该界面

BOOL CMFCWithQtApp::InitInstance()
{CWinApp::InitInstance();QMfcApp::instance(this);MainUI ui;ui.show();QMfcApp::exec();return FALSE;
}

然后编译,这个时候发现会在链接的时候包一些错误,找不到一些 meta 的函数的定义

配置元编译过程

传统的c/c++ 从源代码到生成可执行文件的过程需要经过预编译、编译、链接。而qt在预编译前会进行元编译,生成一个moc_开头的源码文件,后续编译的真正的文件其实是这个元编译生成的文件。MFC项目不会经历这一步,所以会报错。

MainUI.h 上点击右键,选择属性, 将项目类型选择为自定义生成工具

然后应用,这个时候会出现新的选项
在这里插入图片描述
在命令行和输入这两栏中分别填入 "moc.exe" "%(FullPath)" -o ".\GeneratedFiles\moc_%(Filename).cpp" "-fpch.h" "-f../MainUI.h".\GeneratedFiles\moc_%(Filename).cpp

命令行的含义是会使用moc元编译器编译当前文件,并将生成的文件放入到当前目录下的GeneratedFiles子目录中,并且以moc_开头作为文件名,后面 -f 表示生成的新文件中会包含 #include "pch.h"#include "../MainUI.h"

然后在文件中选择右键,编译。这样将会生成moc文件(两边的双引号也好包含进去)

如果编译的时候报找不到moc.exe 这样的错误,请配置QT中的bin路径到环境变量中

我们将新生成的文件添加到项目中
在这里插入图片描述
再次编译,成功过后点击运行就可以看到qt界面已经展示出来了

一些问题的处理

窗口出来了,但是在我的环境下出现两个问题,关闭窗口后进程无法退出;程序退出后出现内存泄露的问题

针对这两个问题可以在QMfcApp.cpp 文件中修改

// 表示在最后一个qt窗口退出时,关闭QApplication
setQuitOnLastWindowClosed(true); //将之前的false改为true
// ~QMfcApp() 中添加这两句,当析构完成后关闭进程
HANDLE hself = GetCurrentProcess();
TerminateProcess(hself, 0);

测试信号槽

我们可以在MainUI中添加信号槽

MainUI::MainUI(QWidget* parent) :QWidget(parent)
{setWindowTitle("Qt Windows");setFixedSize(800, 720);QPushButton* pBtn = new QPushButton(QString::fromLocal8Bit("这是一个Qt按钮"), this);connect(pBtn, &QPushButton::clicked, [=]() {QMessageBox::information(this, QString::fromLocal8Bit("信号槽"), QString::fromLocal8Bit("这是由信号槽弹出来的"));});
}

点击按钮之后,消息框也正常弹出来了

使用qt designer 设计界面

使用 qtdesigner 设计这样一个界面

qtdesigner 会生成一个.ui文件,在qt的开发环境中,会自动使用uic.exe 将这个文件生成一个对应的.h文件。我们先将ui文件导入到项目,并且按照之前的步骤设置自定义生成工具,填入如下命令行

"uic.exe" "%(FullPath)" -o ".\ui_%(Filename).h"

并且填写上输出路径.\ui_%(Filename).h

编译之后会生成一个对应的ui_MainUi.h 文件,修改对应的MainUI.h 头文件,加上关于它的引用,并且添加一个ui的对象指针

//MainUI.h
#pragma once
#include <QWidget>
#include "ui_Main.h"class MainUI: public QWidget
{Q_OBJECT
public:MainUI(QWidget* parent = nullptr);~MainUI();private:Ui::mainUI* m_pUI;
};

在类的构造中,使用ui对象来产生界面元素

//MainUI.cpp
#include "pch.h"
#include "MainUI.h"
#include <QPushButton>
#include <QMessageBox>MainUI::MainUI(QWidget* parent) :QWidget(parent),m_pUI(new Ui::mainUI())
{m_pUI->setupUi(this);connect(m_pUI->pushButton, &QPushButton::clicked, [=]() {QMessageBox::information(this, QString::fromLocal8Bit("qt 信号槽测试"), m_pUI->lineEdit->text());});
}MainUI::~MainUI()
{delete m_pUI;
}

执行效果如下
在这里插入图片描述


http://chatgpt.dhexx.cn/article/6ZtEjkCo.shtml

相关文章

一、MFC登陆界面

一、新建项目 打开VS2022——>创建新项目——>选择MFC应用&#xff0c;点击下一步——>修改项目名称和位置&#xff0c;点击创建——>修改应用程序类型、项目样式经典菜单选项 二、添加预处理指令 VS建议采用带_s的函数&#xff0c;如scanf_s、strcpy_s&#xff0…

MFC基础知识与课程设计思路

引言 本文致力于提供MFC的相关知识&#xff0c;以方便大家更好地认识MFC的使用方法。介绍将会分为以下几个部分&#xff1a;MFC初始文件的理解、MFC我们所使用的框架理解、MFC的进阶用法、MFC我在使用过程中遇到的问题及解决方法。 MFC初始文件的理解 MFC的初始文件中有两项文…

MFC添加程序关闭时时的提示界面

文章目录 MFC一.简介二.方法 MFC 一.简介 在应用程序退出的时候&#xff0c;不能点击叉直接退出&#xff0c;我们想添加一个退出提示。在点击叉后&#xff0c;弹出是否确定退出的界面&#xff0c;如下面的界面&#xff0c;具体操作往下看 二.方法 找到我们需要操作的主界面…

【MFC】模拟采集系统——界面设计(17)

功能介绍 启动界面 开始采集&#xff1a; PS&#xff1a;不涉及 数据保存&#xff0c;重现等功能 界面设计 界面分为三块&#xff1a;顶部黑条带关闭按钮、左边对话框&#xff0c;右边的主界面 资源&#xff1a; 顶部黑条 top.bmp 2* 29 &#xff08;宽 * 高 像素点&…

MFC界面设计入门篇

点击C里的MFC再点击MFCApplication&#xff0c;到下面改名字和路径&#xff0c;然后OK 然后点击Next&#xff0c; 选择single document&#xff0c;MFCstandard&#xff0c;简体中文&#xff0c;然后Finish 这时候可以先直接运行&#xff0c;看看工程的样子&#x…

最最简单的几个Mac终端命令

几个简单的Mac终端命令 目录切换相关 cd空格/ 回到根目录cd空格… &#xff08;或者 cd空格…/&#xff09; 回到上一级目录cd空格. 回到当前目录pwd 显示从根目录到当前目录的完整目录 vi操作相关 注意&#xff1a;vi操作的文件如果不存在&#xff0c;则先自动创建一个该名字…

Mac 终端基本命令

基本命令 1、列出文件 ls 参数 目录名 例: 看看驱动目录下有什么:ls /System/Library/Extensions 参数 -w 显示中文&#xff0c;-l 详细信息&#xff0c; -a 包括隐藏文件 2、转换目录 cd 例&#xff1a;想到驱动目录下溜达一圈 cd /System/Library/Extension…

10需要知道Mac终端命令

如果你想进入web开发领域&#xff0c;知道什么是终端&#xff0c;如何使用终端是非常有益的。在今天的文章中&#xff0c;我们将介绍Mac终端命令的10个必要知识&#xff01; &#x1f642; 什么是终端&#xff08;Terminal&#xff09; 终端最基本的用途是可以浏览计算机的文…

Mac终端命令

Mac电脑安装程序&#xff0c;打开允许任何来源的方法&#xff0c;在终端执行命令行即可。 打开命令&#xff1a;sudo spctl --master-disable 关闭命令&#xff1a;sudo spctl --master-enable Mac终端打开文件 1.打开文件夹的命令很简单&#xff0c;使用 open 文件夹…

Mac终端命令失效( command not found)/

ls vi vim 输入完来一句command not found xx 心哇凉哇凉的&#xff0c;心态都崩了。 guolianggldeMacBook-Pro ~ % cat zsh: command not found: cat guolianggldeMacBook-Pro ~ % ls zsh: command not found: ls guolianggldeMacBook-Pro ~ % mdfind zsh: command not fo…

MacOS系统终端常用命令大全

MacOS系统终端是使用mac电脑的小伙伴需要或多或少了解的一个应用。熟悉并掌握一些基本的常用命令可以帮助我们快速的解决一些日常问题&#xff0c;提高工作效率&#xff0c;下面让小编带大家了解一下吧&#xff01; 基本概念 命令的构成&#xff1a;Command Name、Options、Ar…

Mac终端 常用命令

OSX 的文件系统 OSX 采用的Unix文件系统&#xff0c;所有文件都挂在跟目录 / 下面&#xff0c;所以不在要有Windows 下的盘符概念。 你在桌面上看到的硬盘都挂在 /Volumes 下。 比如接上个叫做 USBHD的移动硬盘&#xff0c;桌面上会显示出一个硬盘图标&#xff0c;它实际在哪…

mac 终端 常用命令

文件目录 首先要清楚几个文件目录&#xff1a; " / " &#xff1a;根目录 " ~ " &#xff1a;用户主目录的缩写。例如当前用户为hello&#xff0c;那么" ~ "展开来就是&#xff1a;/Users/hello " . " &#xff1a;当前目录 "…

RANSAC原理及直线拟合(python动态图解)

一、简介 随机采样一致性&#xff08;Random Sample Consensus&#xff0c;RANSAC&#xff09;由斯坦福国际研究院的Fischler和Bolles于1981年首次提出[1]。RANSAC算法是一种随机参数估计迭代算法&#xff1b;从一组包含异常数据的样本数据集中&#xff0c;通过迭代的方式&…

RANSAC初识

RANSAC算法&#xff1a;随机抽样一致算法&#xff08;random sample consensus,RANSAC&#xff09; 一个简单的例子是从一组观测数据中找出合适的二维直线。假设观测数据中包含局内点和局外点&#xff0c;其中局内点近似的被直线所通过&#xff0c;而局外点远离于直线。简单的…

RANSAC算法详解

RANSAC算法详解 给定两个点p1与p2的坐标&#xff0c;确定这两点所构成的直线&#xff0c;要求对于输入的任意点p3&#xff0c;都可以判断它是否在该直线上。初中解析几何知识告诉我们&#xff0c;判断一个点在直线上&#xff0c;只需其与直线上任意两点点斜率都相同即可。实际…

Ransac拟合椭圆

一、Ransac算法介绍 RANSAC(RAndom SAmple Consensus,随机采样一致)最早是由Fischler和Bolles在SRI上提出用来解决LDP(Location Determination Proble)问题的&#xff0c;该算法是从一组含有“外点”(outliers)的数据中正确估计数学模型参数的迭代算法。“外点”一般指的的数据…

RANSAC算法

算法基本思想和流程 RANSAC是通过反复选择数据集去估计出模型&#xff0c;一直迭代到估计出认为比较好的模型。 具体的实现步骤可以分为以下几步&#xff1a; 选择出可以估计出模型的最小数据集&#xff1b;(对于直线拟合来说就是两个点&#xff0c;对于计算Homography矩阵就…

RANSAC迭代估计

RANSAC迭代估计 1. 定义2. 功能3. 流程4. 迭代次数推导5. 实现直线拟合 1. 定义 根据一组包含异常数据的样本数据集&#xff0c;计算出数据的数学模型参数&#xff0c;得到有效样本数据的算法 从一组含有“外点”(outliers)的数据中正确估计数学模型参数的迭代算法 “外点”一…

RANSAC

转自&#xff1a;http://www.cnblogs.com/xrwang/archive/2011/03/09/ransac-1.html 作者&#xff1a;王先荣 本文翻译自维基百科&#xff0c;英文原文地址是&#xff1a;http://en.wikipedia.org/wiki/ransac&#xff0c;如果您英语不错&#xff0c;建议您直接查看原文。 …