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

目录
  • 添加QT依赖
  • 添加信号槽机制
  • 添加qt界面
  • 配置元编译过程
  • 一些问题的处理
  • 测试信号槽
  • 使用qt designer 设计界面

如果你有一个现成的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开发界面内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++图形界面开发Qt教程:嵌套圆环示例

    目录 嵌套圆环图 运行示例 总结 Qt是一个跨平台框架,通常用作图形工具包,它不仅创建CLI应用程序中非常有用.而且它也可以在三种主要的台式机操作系统以及移动操作系统(如Symbian,Nokia Belle,Meego Harmattan,MeeGo或BB10)以及嵌入式设备,Android(Necessitas)和iOS的端口上运行.现在我们为你提供了免费的试用版. Qt组件推荐: QtitanRibbon| 下载试用: 遵循Microsoft Ribbon UI Paradigm for

  • 手把手教你实现漂亮的Qt 登录界面

    前言 最近在使用Qt5,Qt Creator做一个管理系统类的项目,自然需要用到登录界面,故记录一下登录界面的制作.其中一些功能的实现也得益于之前Qt5基础视频不规则窗口部分的学习. 手把手教你实现漂亮的登录界面 首先看一下成品. 第一步.新建一个Qwidget项目 没必要用qmainwindow,不需要那些菜单,一般用qwidget就可以,注意勾选ui. 第二步.添加界面组件 1.添加容器 调整容器为合适大小,同时调整整个画布为合适大小. 2.添加按钮,标签,文字组件 构思: 账号密码部分使用

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

    目录 添加QT依赖 添加信号槽机制 添加qt界面 配置元编译过程 一些问题的处理 测试信号槽 使用qt designer 设计界面 如果你有一个现成的MFC项目在做维护,但是你厌倦了使用MFC繁琐的操作来做界面美化,或者你需要在这个项目中用到QT里面好用的某些功能:亦或者是你需要使用某些只能在MFC中使用的组件,但是界面这部分已经用QT做好了.那么这篇文章可能可以帮助到你 演示环境使用Visual Studio 2019 + QT5.12.8 版本 添加QT依赖 首先创建一个基于对话框的MFC工

  • 教你在VS2022 MFC程序中调用CUDA代码的方法

    目录 在VS2022 MFC程序中调用CUDA函数 Pre: 安装好CUDA后VS中该有的效果 将CUDA函数集成到MFC项目中 1. 为项目添加CUDA配置 2. 把cuda代码添加到项目中 3. 导出想调用的cuda函数定义 4. 创建CUDA的调用接口(非必须) 在VS2022 MFC程序中调用CUDA函数 Pre: 安装好CUDA后VS中该有的效果 首先,假设你已经安装好了CUDA,并且成功集成在VS2022中(即新建项目有CUDA项目的选项,如下图所示). 你已经有一个MFC项目和一份

  • 详解微信小程序中的页面代码中的模板的封装

    详解微信小程序中的页面代码中的模板的封装 最近在进行微信小程序中的页面开发,其实在c++或者说是js中都会出现这种情况,就是相同的代码会反复出现,这就是进行一定的封装,封装的好处就是可以是程序中在于减少一定的代码量,并且可是使代码结构更加清晰.那今天所要记录的就是关于微信小程序中的页面的模板封装. 在微信小程序中的文件名都带有wxml等样式,在wxml中提供了模板,即可以在模板中定义代码片段,然后可以在页面中的不同位置进行调用,模板的定义: <templatename="products&

  • MFC程序执行过程深入剖析

    本文较为详细的分析了VC++程序设计的MFC程序执行过程,有助于加深对MFC程序运行原理的理解.分享给大家供大家参考之用.具体分析如下: 一 MFC程序执行过程剖析 1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用程序的窗口函数.而在MFC程序当中我们不在能找到类似WinMain这样的程序入口,取而代之的是一系列派生类的声明和定义以及一个冲CWinApp类派生而来的类的全局

  • 微信小程序如何使用云开发

    微信小程序中的云开发想必大家还不是很熟悉,因为云开发也就是9月份上线的,相比之前大家对于数据库的存储都是用的是自己的服务器,接下来这篇文章主要为大家介绍下怎么使用云开发,网上看过很多文章感觉介绍的不是很详细,下面通过我个人亲身经历整理下自己的思路吧. 首先介绍下云开发主要的三大特点,目前提供三大基础能力支持: 云函数:在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码 数据库:一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库 存储:在小程序前端直接上传/下载云

  • VC中使用ADO开发数据库应用程序简明教程

    本文实例讲述了VC中使用ADO开发数据库应用程序的方法.分享给大家供大家参考,具体如下: 一.ADO概述 ADO是Microsoft为最新和最强大的数据访问范例 OLE DB 而设计的,是一个便于使用的应用程序层接口.ADO 使您能够编写应用程序以通过 OLE.DB 提供者访问和操作数据库服务器中的数据.ADO 最主要的优点是易于使用.速度快.内存支出少和磁盘遗迹小.ADO 在关键的应用方案中使用最少的网络流量,并且在前端和数据源之间使用最少的层数,所有这些都是为了提供轻量.高性能的接口.之所以

  • Android开发之在程序中时时获取logcat日志信息的方法(附demo源码下载)

    本文实例讲述了Android开发之在程序中时时获取logcat日志信息的方法.分享给大家供大家参考,具体如下: 今天分享一个在软件开发中很实用的例子,也是这几天在通宵加班中我使用的一个小例子, 在程序中监听Log信息. 为什么说它实用?原因是Android的开发厂商各种修改之后手机和手机之间以后存在很多差异.比如说魅族M9手机 开发中如果项目中涉及到访问手机系统的地方,例如访问系统短信库,M9手机它会提示一个dialog框 让用户自己去选择 访问还是不访问.这样就给开发适配带来了巨大的麻烦.本来

  • Qt之ui在程序中的使用-多继承法介绍

    thirdDialog.h 复制代码 代码如下: #ifndef THIRDDIALOG_H #define THIRDDIALOG_H #include <QtGui> #include "ui_third.h" class thirdDialog:public QDialog,private Ui::Third { Q_OBJECT public: thirdDialog(QWidget *parent=0); ~thirdDialog(); }; #endif thi

  • Linux 命令查询小程序中的 WePY 云开发实践

    大家好,今天我来为大家分享一下, Linux 命令查询小程序中的 WePY 云开发实践. Why WePY 首先,先分享一下为什么要选择 WePY ? 在项目开始进行选型的时候,我可选的底层框架有 WePy.MPVue.Taro.MinUI,这些框架都是工程化做得很好的框架,可以帮助小程序项目长期进行维护.其中,Taro 因为采用的是我所不熟悉的 React ,所以从一开始就被排除.MPVue 我看了以后,它更多是给 Web 开发者提供小程序转化工具,而不是给小程序开发者提供类 Vue 工具,所

  • Android开发中简单设置启动界面的方法

    本文实例讲述了Android开发中简单设置启动界面的方法.分享给大家供大家参考,具体如下: 启动界面的意义是为了让后台处理耗时的复杂工作,当工作处理完成后,即可进入主界面.相比让用户等待布局加载完成,使用一张图片作为启动背景,会带来更好的体验. 首先,需要建立一个简单的布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas

随机推荐