Masimaro's blog - mfc
type: channel
link: https://www.masimaro.top/tag/mfc/
items: MFC程序中使用QT开发界面
items: 使用miniblink 在程序中嵌入浏览器

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…

使用miniblink 在程序中嵌入浏览器
type: item
date: 2019-03-17T14:01:00+08:00
description: 最近公司产品中自定义浏览器比较老，打开一些支持h5 的站莫名报错，而且经常弹框。已经到了令人无法忍受的地步了，于是我想到了将内核由之前的IE 升级到Chromium。之前想到的是使用cef来做，而且网上的资源和教程也很多，后来在自己尝试的过程中发现使用cef时程序会莫名其妙的崩溃，特别是在关闭对话框的时候。我在网上找了一堆资料，尝试了各种版本未果，这个方案也就放弃了。后来又搜到了wke和miniblink，对比二者官方的文档和demo，我决定使用miniblink，毕竟我直接搜索wke browser 出来的都是miniblink，只有搜索wke github 才会有真正的wke，而且wke似乎没有api文档，最后miniblink是国人写的，文档都是中文而且又有专门的qq交流群，有问题可以咨询一下。什么是miniblinkminiblink 是由国内大神 龙泉寺扫地僧 针对chromium内核进行裁剪去掉了所有多余的部件，只保留最基本的排版引擎blink，而产生的一款号称全球小巧的浏览器内核项目，目前miniblink 保持了10M左右的极简大小，相比CEF 动辄几百M的大小确实小巧许多。而且能很好的支持H5等一些列新标准，同时它内嵌了Nodejs 支持electron。而且也支持各种语言调用。官方的地址如下为 https://weolar.github.io/miniblink/index.html使用miniblink说了这么多那么该怎么用呢？从官方的介绍来看，我们可以使用VS的向导程序生成一个普通的win32 窗口程序，然后生成的这些代码中将函数InitInstance 中的代码全部删除加上这么5句话wkeSetWkeDllPath(L"E:\\mycode\\miniblink49\\trunk\\out\\Release_vc6\\node.dll"); wkeInitialize(); wkeWebView window = wkeCreateWebWindow(WKE_WINDOW_TYPE_POPUP, NULL, 0, 0, 1080, 680); wkeLoadURL(window, "qq.com"); wkeShowWindow(window, TRUE);当然，使用这些函数需要下载它的SDK开发包，然后在对应位置包含wke.h。这些代码会生成一个窗口程序，具体的请敢兴趣的朋友自己去实践看看效果。或者编译运行一下它的demo程序。在对话框中使用现在我想在对话框中使用，那么该怎么办呢。首先也是先用MFC的向导生成一个对话框并编辑资源文件。最后我的对话框大概长成这样我会将按钮下面部分全部作为浏览器页面。我们在程序APP类的InitInstance函数 中初始化miniblink库,并在对话框被关闭后直接卸载miniblink的相关资源wkeSetWkeDllPath(L"node.dll"); wkeInitialize(); CWebBrowserDlg dlg = CWebBrowserDlg(); m_pMainWnd = dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: 在此放置处理何时用 // “确定”来关闭对话框的代码 } else if (nResponse == IDCANCEL) { // TODO: 在此放置处理何时用 // “取消”来关闭对话框的代码 } // 由于对话框已关闭，所以将返回 FALSE 以便退出应用程序， // 而不是启动应用程序的消息泵。 wkeFinalize();然后在主对话框类中新增一个成员变量用来保存miniblink的web视图的句柄wkeWebView m_web;我们在对话框的OnInitDialog函数中创建这么一个视图，用来加载百度的首页面GetClientRect(&rtClient); rtClient.top += 24; m_web = wkeCreateWebWindow(WKE_WINDOW_TYPE_CONTROL, *this, rtClient.left, rtClient.top, rtClient.right - rtClient.left, rtClient.bottom - rtClient.top); wkeLoadURL(m_web, "https://www.baidu.com"); wkeShowWindow(m_web, TRUE);至此我们已经能够生成一个简单的浏览器程序似乎到这已经差不多该结束了，但是现在我遇到了在整个程序完成期间最大的问题，那就是web页面无法响应键盘消息，我尝试过改成窗口程序，发现改了之后能正…