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

 更新时间:2021年12月10日 17:02:48   作者:aluluka  
本文主要介绍了MFC程序中使用QT开发界面的实现步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

如果你有一个现成的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 new
    object. The returned object must be destroyed by the caller.

    Use this static function if you want to perform additional
    initializations after creating the application object, or if you
    want to create Qt GUI elements in the InitInstance()
    reimplementation of CWinApp:

    \code
    BOOL MyMfcApp::InitInstance()
    {
    // standard MFC initialization
    // ...

    // This sets the global qApp pointer
    QMfcApp::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;
}

执行效果如下

在这里插入图片描述

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

相关文章

  • C++ 封装 DLL 供 C# 调用详细介绍

    C++ 封装 DLL 供 C# 调用详细介绍

    这篇文章主要介绍了C++ 封装 DLL 供 C# 调用(以C# 调用C++ 二次封装的VLC播放库为介质,支持回调函数的封装),需要的朋友可以参考下面我文章的具体内容
    2021-09-09
  • C++实现关系与关系矩阵的代码详解

    C++实现关系与关系矩阵的代码详解

    这篇文章主要介绍了C++实现关系与关系矩阵,功能实现包括关系的矩阵表示,关系的性质判断及关系的合成,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • UE4 Unlua 调用异步蓝图节点AIMoveTo函数示例详解

    UE4 Unlua 调用异步蓝图节点AIMoveTo函数示例详解

    这篇文章主要为大家介绍了UE4 Unlua 调用AIMoveTo函数示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • C语言实现单元测试的示例详解

    C语言实现单元测试的示例详解

    单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。这篇文章主要为大家介绍了C语言实现单元测试的方法,需要的可以参考一下
    2022-09-09
  • C语言基础知识变量的作用域和存储方式详细介绍

    C语言基础知识变量的作用域和存储方式详细介绍

    这篇文章主要介绍了C语言基础知识变量的作用域和存储方式详细介绍的相关资料,需要的朋友可以参考下
    2017-01-01
  • C++ 自定义栈实现迷宫求解

    C++ 自定义栈实现迷宫求解

    这篇文章主要介绍了C++ 自定义栈实现迷宫求解的相关资料,需要的朋友可以参考下
    2017-07-07
  • C/C++程序开发中实现信息隐藏的三种类型

    C/C++程序开发中实现信息隐藏的三种类型

    这篇文章主要介绍了C/C++程序开发中实现信息隐藏的三种类型的相关资料,需要的朋友可以参考下
    2016-02-02
  • 如何利用C语言实现最简单的HTTP服务器详解

    如何利用C语言实现最简单的HTTP服务器详解

    这篇文章主要给大家介绍了关于如何利用C语言实现最简单的HTTP服务器的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C语言具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-11-11
  • C++卸载程序功能示例

    C++卸载程序功能示例

    用C++写一个自己的卸载程序来完成程序的卸载工作,同时运行后要删除卸载程序本身,并删除卸载程序所在的文件夹
    2013-11-11
  • Visual Studio2000系列版本安装OpenGL的图文教程

    Visual Studio2000系列版本安装OpenGL的图文教程

    这篇文章主要介绍了Visual Studio2000系列版本安装OpenGL的图文教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04

最新评论