文章目录
- 一、前言
- 二、miniblink简介
- 三、miniblink使用
- 四、运行效果
- 五、工程结构
一、前言
本文取自刘典武大师:Qt编写地图综合应用58-兼容多浏览器内核
用Qt做项目过程中,遇到需要用到浏览器控件的项目,可能都会绕不开一个问题,那就是从Qt5.6版本开始mingw编译器的Qt构建套件,不再提供浏览器控件了,之前还可以用webkit
控件,这下很多项目要么选择5.6以下版本,要么选择msvc的构建套件,而且大部分的msvc构建套件还不自带浏览器控件,也需要自己编译,只有原配的构建套件比如Qt5.9+VS2015、Qt5.12+VS2017这种搭配才可能有浏览器控件,不然就算你勾选了浏览器控件也不会安装,这样就使得很多依赖浏览器控件的项目比较被动。
于是必须寻找一个轻量级的浏览器控件来替代,比如cef
、miniblink
,个人更倾向于miniblink
,用法极其简单,依赖极其精简就一个dll
,在linux
和mac
系统上本来qt
就一直会有浏览器控件,所以也就不涉及到跨平台的问题,所以miniblink
暂支持windows
的缺点也就不算缺点了。
二、miniblink简介
屌炸天的内核来袭,史上最小chromium内核miniblink!
miniblink github
miniblink
是一个追求极致小巧的浏览器内核项目,全世界第三大流行的浏览器内核控件。其基于chromium
最新版内核,去除了chromium
所有多余的部件,只保留最基本的排版引擎blink
。miniblink
保持了10M左右的极简大小,是所有同类产品最小的体积,同时支持windows xp
、npapi
。
qt+miniblink用法步骤:
- 第一步:调用
wkeSetWkeDllPath
函数加载dll文件路径,一个项目只需要执行一次。 - 第二步:调用
wkeInitialize
初始化动态库,一个项目只需要执行一次。 - 第三步:调用
wkeCreateWebWindow
创建一个浏览器控件,传入句柄。 - 第四步:调用
wkeOnLoadingFinish
注册回调加载完成信号,有需要才注册。 - 第五步:调用
wkeJsBindFunction
注册回调接收数据的方法,一定要放在这里在网页加载前执行。 - 第六步:调用
wkeLoadURL
加载网址、wkeLoadFile
加载网页文件、wkeLoadHtmlWithBaseUrl
加载网页内容。 - 第七步:调用
wkeRunJS
执行js
函数,超级简单。 - 第八步:调用
wkeFinalize
释放资源,只要执行一次,在整个项目结束的时候。
三、miniblink使用
使用miniblink
需要三个文件:wke.h
、miniblink.dll
、miniblink_64.dll
刘典武大师封装了一个miniblink
浏览器类
#ifndef MINIBLINK_H
#define MINIBLINK_H#include <QWidget>
#include "wke.h"class miniblink : public QWidget
{Q_OBJECT
public:explicit miniblink(QWidget *parent = 0);//初始化资源static void init();//释放资源static void release();protected://设置浏览器控件自动适应大小void resizeEvent(QResizeEvent *);private://浏览器控件对象wkeWebView webView;signals://网页载入完成void loadFinished(bool ok);//收到网页发出来的数据void receiveDataFromJs(const QString &type, const QVariant &data);public://给回调用的函数void loadFinish(bool ok);void receiveData(const QString &type, const QVariant &data);public slots://加载网址或者本地文件void load(const QString &url, bool file = false);//加载html内容void setHtml(const QString &html, const QString &baseUrl);//执行js函数void runJs(const QString &js);
};#endif // MINIBLINK_H
#pragma execution_character_set("utf-8")
#include "miniblink.h"
#include "qapplication.h"
#include "qmessagebox.h"
#include "qdatetime.h"
#include "qfile.h"
#include "qvariant.h"
#include "qdebug.h"#define TIMEMS QTime::currentTime().toString("hh:mm:ss zzz")
void onLoadingFinish(wkeWebView, void *param, const wkeString, wkeLoadingResult result, const wkeString)
{//qDebug() << "onLoadingFinish" << result;//在注册函数的地方就已经传入了类指针miniblink *widget = (miniblink *)param;//0 = WKE_LOADING_SUCCEEDED, 1 = WKE_LOADING_FAILED, 2 = WKE_LOADING_CANCELEDwidget->loadFinish(result == 0);
}jsValue WKE_CALL_TYPE objName_receiveData(jsExecState es, void *param)
{if (0 == jsArgCount(es)) {return jsUndefined();}//挨个取出参数,设定的通用方法,只有两个参数jsValue arg0 = jsArg(es, 0);jsValue arg1 = jsArg(es, 1);if (!jsIsString(arg0)) {return jsUndefined();}//在注册函数的地方就已经传入了类指针miniblink *widget = (miniblink *)param;QString type = QString::fromStdString(jsToString(es, arg0));QVariant data = QString::fromStdString(jsToString(es, arg1));widget->receiveData(type, data);return jsUndefined();
}miniblink::miniblink(QWidget *parent) : QWidget(parent)
{//第一步先初始化动态库init();//第二步初始化浏览器控件//创建一个浏览器控件,放入句柄webView = wkeCreateWebWindow(WKE_WINDOW_TYPE_CONTROL, (HWND)this->winId(), 0, 0, this->width(), this->height());//关联完成信号wkeOnLoadingFinish(webView, onLoadingFinish, this);//设置浏览器控件可见wkeShowWindow(webView, TRUE);//注册通用的接收数据的方法,一定要放在这里在网页加载前执行wkeJsBindFunction("objName_receiveData", objName_receiveData, this, 2);
}void miniblink::init()
{//全局只需要初始化一次static bool isInit = false;if (!isInit) {isInit = true;//不同的构建套件位数加载不同的动态库
#ifdef Q_OS_WIN64QString flag = "64";QString file = qApp->applicationDirPath() + "/miniblink_64.dll";
#elseQString flag = "32";QString file = qApp->applicationDirPath() + "/miniblink.dll";
#endif//如果文件不存在则提示if (!QFile(file).exists()) {QMessageBox::critical(0, "错误", file + "\n文件不存在请先拷贝!");return;}const wchar_t *path = reinterpret_cast<const wchar_t *>(file.utf16());wkeSetWkeDllPath(path);bool ok = wkeInitialize();qDebug() << TIMEMS << QString("init miniblink_%1 %2").arg(flag).arg(ok ? "ok" : "error");}
}void miniblink::release()
{wkeFinalize();
}void miniblink::resizeEvent(QResizeEvent *)
{wkeResize(webView, this->width(), this->height());
}void miniblink::loadFinish(bool ok)
{emit loadFinished(ok);
}void miniblink::receiveData(const QString &type, const QVariant &data)
{emit receiveDataFromJs(type, data);
}void miniblink::load(const QString &url, bool file)
{QByteArray data = url.toUtf8();const char *temp = data.data();if (file) {wkeLoadFile(webView, temp);} else {wkeLoadURL(webView, temp);}
}void miniblink::setHtml(const QString &html, const QString &baseUrl)
{QByteArray dataHtml = html.toUtf8();QByteArray dataUrl = baseUrl.toUtf8();wkeLoadHtmlWithBaseUrl(webView, dataHtml.data(), dataUrl.data());
}void miniblink::runJs(const QString &js)
{QByteArray data = js.toUtf8();wkeRunJS(webView, data.data());
}
有了这个浏览器类之后,就可以正常的调用接口了
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "miniblink.h"namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private:Ui::Widget *ui;miniblink *webView;private slots:void initForm();//网页载入完成void loadFinished(bool ok);//收到网页发出来的数据void receiveDataFromJs(const QString &type, const QVariant &data);private slots:void on_btnLoadUrl_clicked();void on_btnLoadFile_clicked();void on_btnLoadHtml_clicked();void on_btnRunJs_clicked();void on_horizontalSlider_valueChanged(int value);
};#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include "qapplication.h"
#include "qdebug.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->initForm();on_btnLoadFile_clicked();
}Widget::~Widget()
{delete ui;
}void Widget::initForm()
{webView = new miniblink;connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));connect(webView, SIGNAL(receiveDataFromJs(QString, QVariant)),this, SLOT(receiveDataFromJs(QString, QVariant)));ui->gridLayout->addWidget(webView, 0, 0);
}void Widget::loadFinished(bool ok)
{qDebug() << "加载完成" << ok;
}void Widget::receiveDataFromJs(const QString &type, const QVariant &data)
{qDebug() << "收到数据" << type << data;
}void Widget::on_btnLoadUrl_clicked()
{webView->load("https://www.baidu.com");
}void Widget::on_btnLoadFile_clicked()
{webView->load(qApp->applicationDirPath() + "/demo.html", true);
}void Widget::on_btnLoadHtml_clicked()
{QStringList html;html << "<html><body>";html << "<h2>Hello World</h2>";html << "</body></html>";webView->setHtml(html.join(""), "");
}void Widget::on_btnRunJs_clicked()
{webView->load(qApp->applicationDirPath() + "/gauge.html", true);
}void Widget::on_horizontalSlider_valueChanged(int value)
{QString js = QString("setGaugeValue(%1)").arg(value);webView->runJs(js);
}
四、运行效果
需要把
miniblink.dll
、miniblink_64.dll
放到可执行文件目录下,才能运行起来