文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MFC程序中使用QT开发界面的实现步骤

2024-04-02 19:55

关注

如果你有一个现成的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的注释里面可以看到,如何使用它



首先在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;
}

执行效果如下

在这里插入图片描述

到此这篇关于MFC程序中使用QT开发界面的实现步骤的文章就介绍到这了,更多相关MFC QT开发界面内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯