Masimaro's blog - ui
type: channel
link: https://www.masimaro.top/tag/ui/
items: MFC程序中使用QT开发界面
items: duilib基本框架

MFC程序中使用QT开发界面
type: item
date: 2021-12-10T09:26:00+08:00
description: 如果你有一个现成的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…

duilib基本框架
type: item
date: 2016-07-27T21:44:00+08:00
description: 最近我一个同学在项目中使用到了duilib框架，但是之前并没有接触过，他与我讨论这方面的内容，看着官方给出的精美的例子，我对这个库有了很大的兴趣，我自己也是初学这个东东，我在网上花了不少时间来找相关的资料，但是找到的不多，官方给的文档又不全面，但是我还是找到了一些博主贡献的优秀的博文，现在我是通过博文上的讲解加上自己查看源代码的一些心得，正在艰难的前行。现在正在看的是博主Alberl在博客园中的duilib基础教程中的内容，下面的代码都是在他博客中给出代码的基础上做了一点小小的修改。点击这里跳转到对应的博客，以及博主夜雨無聲的博客，博客地址duilib的简介国内首个开源 的directui 界面库,它提供了一个所见即所得的开发工具——UIDesigner，它只有主框架窗口，其余的空间全部采用绘制的方式实现，所以对于控件来说没有句柄和窗口类等内容，它通过UIDesigner工具将用户定义的窗口保存在xml文件中，在创建窗口时读取xml文件中的内容，来绘制相应的控件。目前有许多界面采用duilib编写，大家可以去网上搜集相关资料。环境的配置首先我们去github上获取相关的源代码，这个是对应的项目地址：https://github.com/duilib/duilib下载完后，在目录中找到一个.sln结尾的文件，使用visual studio编译器打开，打开后发现有一个duilib的项目，以及其他，其实真正有用的就是这个duilib，其余的都是官方给出的例子代码。一般只需要编译这个duilib项目就可以了，当初没注意直接点了编译全部的，结果报了一堆错误，其实都是没有对应的lib和dll文件造成的。在VS环境下有一个编译选项，如下图所示上面有4个编译选项，最好将所有的都编译一遍，这样在对应项目的bin目录下会生成四个dll文件，这几个文件分别是debug下的UNICODE编码文件、ANSI文件以及Release版本下的UNICODE编码文件、ANSI文件。u代表unicode d代表debug。另外在lib目录下会生成对应的lib文件。在新建的工程中，点击属性在属性对话框中选择VC++目录，在源文件，库文件，包含文件中将对应的路径添加进去，分别是项目目录和lib文件目录。如下图（刚开始有点问题所以添加的内容有点多，但是不影响正常使用）：最后可以在环境变量的Path变量中添加对应的dll路径，这样就不需要将dll文件拷贝到自己项目的exe文件所在位置处。其实上述的环境可以不用设置，如果不设置，在编写程序包含相关路径时就需要给定完整的路径。到此处为止，整个开发环境就已经搭建好了，剩下的就是代码的编写了。基本的框架窗口首先新建一个Win32类型的项目，添加主函数。然后创建一个新类，我们叫做CDuiFrameWnd，下面是类的源代码//头文件 #include <DuiLib\UIlib.h> using namespace DuiLib; class CDuiFrameWnd : public CWindowWnd { public: CDuiFrameWnd(); ~CDuiFrameWnd(); virtual LPCTSTR GetWindowClassName() const; virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); protected: CPaintManagerUI m_PaintManager; };//cpp文件 LPCTSTR CDuiFrameWnd::GetWindowClassName() const { return _T("DuiFrameWnd"); } LRESULT CDuiFrameWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = 0; if (WM_CLOSE == uMsg) { ::CloseWindow(m_hWnd); ::DestroyWindow(m_hWnd); } if (WM_DESTROY == uMsg) { ::PostQuitMessage(0); } return __super::HandleMessage(uMsg, wParam, lParam); }为了能够使用对应的dll文件，还需要引入对应的lib文件，我们在公共的头文件中加入如下代码#ifdef _DEBUG # ifdef _UNICODE # pragma comment(lib, "Duilib_ud.lib") # else # pragma comment(lib, "Duilib_d.lib") …