Qt-Web混合开发-CEF加载网页简单示例(12) 原创

Qt-Web混合开发-CEF加载网页简单示例💙🍓

更多精彩内容
👉个人内容分类汇总 👈
👉Qt - Web混合开发👈

1、概述🐛🦆

  • Qt版本:V5.12.5
  • 编译器:MSVC2017-64
  • CEF版本:91.0.4472.164

CEF(Chromium Embedded Framework)是一种用于嵌入式浏览器的框架,它可以让开发者在自己的应用程序中嵌入一个完整的浏览器窗口,提供与Web页面交互的能力,使用CEF可以快速开发出精美的界面。以下是使用CEF的一些优点:

  1. 灵活性:CEF提供了许多API和插件,使开发者可以自由地定制和扩展浏览器功能,以满足自己的需求。
  2. 多平台支持:CEF支持多种操作系统,包括Windows、Linux和Mac OS X等,使开发者可以在不同平台上使用相同的代码。
  3. 轻量级:CEF可以嵌入到任何C/C++应用程序中,无需安装额外的软件和插件,因此可以减少应用程序的大小和依赖性。
  4. 安全性:使用CEF可以避免一些安全漏洞,例如XSS(跨站脚本)和CSRF(跨站请求伪造)等。
  5. 性能:CEF使用Chromium作为底层引擎,具有优秀的性能和稳定性,可以提供快速的Web浏览体验。

在实际应用中,CEF被广泛用于各种场景,例如游戏客户端、桌面应用程序、图形界面设计等。它可以让开发者在自己的应用程序中嵌入Web浏览器,为用户提供更丰富的Web应用体验和功能。

一些使用了CEF的国内互联网大厂和软件:

  1. 腾讯:腾讯的QQ浏览器就是基于CEF开发的。同时,腾讯的部分游戏客户端、视频客户端等也使用了CEF。
  2. 百度:百度的部分软件,例如网盘客户端、输入法等,也使用了CEF。
  3. 360公司:360公司的部分软件,例如浏览器、安全卫士等,也使用了CEF。
  4. 哔哩哔哩:哔哩哔哩的客户端也使用了CEF,它可以让用户在客户端中观看B站的视频。
  5. 网易:网易的部分游戏客户端和音乐客户端也使用了CEF。

2、实现效果😅🙏

在这里插入图片描述

3、实现功能🐮🐴

  1. QT使用QCefView+CEF实现加载网页功能,相较于QWebEngineView更加稳定,强大;
  2. 演示了如何加载本地html文件和在线网页;
  3. 自动将依赖文件(html、CEF动态库)安装到可执行程序路径下;
  4. 详细注释了使用到的 Chrome命令;

4、Qt部分关键代码💳🛣️🍐

  • pro文件
#---------------------------------------------------------------------------------------
# @功能:       Qt使用cef加载网页简单示例
# @编译器:     Desktop Qt 5.12.5 MSVC2017 64bit(也支持其它编译器)
# @Qt IDE:    D:/Qt/Qt5.12.5/Tools/QtCreator/share/qtcreator
#
# @开发者     mhf
# @邮箱       1603291350@qq.com
# @时间       2023-02-05 12:08:27
# @备注       在父工程中定义依赖库的路径CefPath,如果直接编译当前工程,则需要指定CefPath
#---------------------------------------------------------------------------------------
QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

FORMS += \
    widget.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

#  定义程序版本号
VERSION = 1.0.0
DEFINES += APP_VERSION=\\\"$$VERSION\\\"

# 程序输出路径
contains(QT_ARCH, i386){        # 使用32位编译器
    CONFIG(release, debug|release){
        DESTDIR = $$PWD/../bin
    }else:CONFIG(debug, debug|release){
        DESTDIR = $$PWD/../bind
    }
}else{
    CONFIG(release, debug|release){
        DESTDIR = $$PWD/../bin64
    }else:CONFIG(debug, debug|release){
        DESTDIR = $$PWD/../bin64d
    }
}

# CEF 库的路径, 如果路径为空则不编译当前工程
win32{
    CefPath = E:/lib/QCefView
}
unix:!macx{
}

# 导入库头文件的路径
INCLUDEPATH += $$CefPath/include
DEPENDPATH += $$CefPath/include

# Debug和release的库路径不同
CONFIG(release, debug|release){
    cefDLL.files = $$CefPath/bin/*
    LIBS += -L$$CefPath/lib/ -lQCefView
}else:CONFIG(debug, debug|release){
    cefDLL.files = $$CefPath/bind/*
    LIBS += -L$$CefPath/libd/ -lQCefView
}

# 自动安装依赖文件和库文件
cefDLL.path = $$DESTDIR
webFile.path = $$DESTDIR
webFile.files = $$PWD/hello.html

# msvc需要配置【Custom Process Step: nmake install】或者【Custom Process Step: D:\Qt\Qt5.12.5\Tools\QtCreator\bin\jom.exe install】才生效,或者自己手动拷贝
# Debug和Release需要分别配置
# 执行之前先qmake,如果不想每次手动qmake,可以点击【工具】->【选项】->【构建和运行】->【qmake】->勾选【Run qmake every build】
!exists($$webFile.path/hello.html): INSTALLS += webFile      # 将hello.html拷贝到path路径下
!exists($$cefDLL.path/QCefView.dll): INSTALLS += cefDLL      # 将CEF库文件拷贝到path路径下

# msvc >= 2017  编译器使用utf-8编码
msvc {
    greaterThan(QMAKE_MSC_VER, 1900){       # msvc编译器版本大于2015
        QMAKE_CFLAGS += /utf-8
        QMAKE_CXXFLAGS += /utf-8
    }else{
        message(msvc2015及以下版本在代码中使用【pragma execution_character_set("utf-8")】指定编码)
    }
}

  • widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include "QCefSetting.h"
#include "QCefView.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    QCefView* cefViewWidget = nullptr;
};
#endif // WIDGET_H

  • widget.cpp
#include "widget.h"
#include "ui_widget.h"

#include <qdir.h>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle(QString("Qt使用cef加载网页简单示例 - V%1").arg(APP_VERSION));  // 设置窗口标题

    // 构建web资源的路径
#if 1        // 在线显示网页
    QString uri = "https://www.baidu.com";
#else        // 显示本地html
    QDir dir = QCoreApplication::applicationDirPath();
    QString uri = QString("file://") + QDir::toNativeSeparators(dir.filePath("hello.html"));
#endif

    // 每个QCefView的生成设置
    QCefSetting setting;
    // 设置背景色
    setting.setBackgroundColor(QColor::fromRgb(255, 255, 255));

    // 创建QCefView小部件并将其添加到布局容器
    cefViewWidget = new QCefView(uri, &setting, this);
    ui->gridLayout->addWidget(cefViewWidget);
}

Widget::~Widget()
{
    delete ui;
}


  • main.cpp
#include "widget.h"

#include <QApplication>
#include <QCefContext.h>

void initCefConfig(QCefConfig& config)
{
    config.setUserAgent("QCefViewTest");                        // 设置用户代理
    config.setLogLevel(QCefConfig::LOGSEVERITY_DEFAULT);        // 设置日志级别
    config.setBridgeObjectName("CallBridge");                   // 设置网桥对象名称
    config.setRemoteDebuggingPort(9000);                        // 设置远程调试端口
    config.setBackgroundColor(QColor::fromRgba(qRgba(255, 0, 0, 0)));  // 设置网页的背景色

    config.addCommandLineSwitch("enable-media-stream");
    config.addCommandLineSwitch("use-mock-keychain");
    config.addCommandLineSwitch("allow-file-access-from-files");
    config.addCommandLineSwitch("disable-spell-checking");
    config.addCommandLineSwitch("disable-site-isolation-trials");
    config.addCommandLineSwitch("enable-aggressive-domstorage-flushing");
    // 将具有值的开关添加到用于初始化CEF的命令行参数中
    config.addCommandLineSwitchWithValue("renderer-process-limit", "1");
    config.addCommandLineSwitchWithValue("disable-features", "BlinkGenPropertyTrees,TranslateUI,site-per-process");
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);


    // 使用config初始化QCefContext实例
    QCefConfig config;
    initCefConfig(config);
    QCefContext cefContext(&a, argc, argv, &config);
    // 获取可执行程序所在的路径,然后添加 bin 目录到库的搜索路径中

    Widget w;
    w.show();
    return a.exec();
}

Chrome命令说明

  • enable-media-stream

    用于启用媒体流(Media Stream)功能。Media Stream 是 HTML5 中的一项新特性,

    它允许浏览器通过 WebRTC(Web Real-Time Communication)技术实现音频、视频、屏幕共享等功能,为实时通信提供了强大的支持。

    例如,通过 Media Stream,可以实现浏览器端的视频会议、语音聊天、桌面共享等功能。

    默认情况下,Chromium 浏览器已经启用了 Media Stream 功能,因此一般情况下不需要添加 enable-media-stream 参数。

    但如果您在使用 Chromium 浏览器时遇到了一些与媒体流相关的问题,例如无法共享屏幕或摄像头等,可能需要检查该参数是否被正确设置。

  • use-mock-keychain

    use-mock-keychain 是 macOS 中的一个命令行参数,用于在模拟环境下使用 Keychain,而不是使用真实的 Keychain。Keychain 是 macOS 中的一项安全功能,用于存储和管理用户的密码、证书和其他敏感信息。

    应用程序可以通过 Keychain API 访问这些信息,从而实现自动登录、自动填充表单等功能。在模拟环境下,如果不想使用真实的 Keychain,可以通过添加 use-mock-keychain 参数来使用模拟环境中的 Keychain。

    在使用该参数时,需要注意以下几点:

    仅在模拟环境下使用该参数。在实际的生产环境中,应当使用真实的 Keychain。

    使用模拟 Keychain 时,存储的密码和其他敏感信息仅存储在内存中,不会写入到硬盘中,因此不会在多次启动应用程序之间保留。

    模拟 Keychain 中存储的信息不会被其他应用程序访问,因此仅适用于单个应用程序的测试和开发场景。

  • allow-file-access-from-files

    用于允许浏览器访问本地文件系统。默认情况下,Chromium 浏览器禁止通过 file:// 协议访问本地文件系统中的文件,以防止恶意脚本窃取本地文件信息。但在某些情况下,用户可能需要使用 file:// 协议访问本地文件系统,例如在本地开发网页或调试 JavaScript 代码时。

    通过添加 allow-file-access-from-files 参数,可以在 Chromium 浏览器中启用对 file:// 协议的访问权限。需要注意的是,在启用该参数时,浏览器的安全性可能会受到一定程度的降低,因为恶意脚本可能会通过 file:// 协议访问本地文件系统中的敏感信息。

    因此建议仅在必要情况下使用该参数,并在使用时加强对本地文件系统的保护和监控。

  • disable-spell-checking

    用于禁用拼写检查功能。拼写检查是浏览器的一项功能,用于检查用户在输入表单、文本框等地方输入的文本是否存在拼写错误,并给出相应的纠正建议。

    如果用户需要输入一些特殊的术语、专业名词等,拼写检查可能会对输入造成干扰。

    因此,如果您使用 Chromium 浏览器时需要输入一些特殊的术语、专业名词等,可能会通过添加 disable-spell-checking 参数来禁用拼写检查功能,以避免输入干扰。

    但需要注意的是,禁用拼写检查功能可能会导致输入错误的单词无法被及时发现和纠正,因此建议仅在必要情况下使用该参数。

  • disable-site-isolation-trials

    用于禁用站点隔离试验功能。站点隔离是一项安全功能,它能够将不同站点的网页内容隔离开来,防止恶意网站通过跨站点脚本攻击(XSS)等方式盗取用户的敏感信息。

    站点隔离试验是一种用于测试站点隔离功能的实验性功能,它可能会导致某些网页无法正常加载或出现其他问题。

    因此,如果您使用 Chromium 浏览器时遇到了一些网页加载问题,可能可以通过添加 disable-site-isolation-trials 参数来禁用站点隔离试验功能,以解决这些问题。

    不过需要注意的是,禁用站点隔离试验功能可能会降低浏览器的安全性,因此建议仅在必要情况下使用该参数。

  • enable-aggressive-domstorage-flushing

    用于启用 DOM 存储数据的积极刷新。

    DOM 存储是一种浏览器提供的机制,用于在客户端存储数据,包括 localStorage 和 sessionStorage。

    默认情况下,当页面的 DOM 存储发生更改时,浏览器会在适当的时候将这些更改写入到磁盘中。

    但是,由于写操作可能会影响性能,因此浏览器不会立即将更改写入磁盘,而是将多个更改缓冲在内存中,直到达到一定的阈值才一次性写入磁盘。

    通过添加 enable-aggressive-domstorage-flushing 参数,可以启用 DOM 存储数据的积极刷新,即每次发生更改时立即将更改写入磁盘,以确保数据的及时保存。

    需要注意的是,启用该参数可能会影响浏览器的性能,因为频繁的磁盘写入操作会增加系统的负载。因此建议仅在必要情况下使用该参数,并在使用时加强对系统资源的监控和管理。

  • renderer-process-limit

    用于限制每个站点(域名)可以使用的渲染进程数量。

    在 Chromium 浏览器中,每个站点可以使用多个渲染进程,以提高浏览器的性能和稳定性。

    但是,如果某个站点占用了过多的渲染进程,可能会导致其他站点无法正常渲染,甚至导致浏览器崩溃。

    通过添加 renderer-process-limit 参数,可以限制每个站点可以使用的渲染进程数量,以确保每个站点都能够合理地使用系统资源。

    需要注意的是,该参数的默认值为 0,表示不限制渲染进程数量,因此需要手动设置该参数的值,才能实现对渲染进程数量的限制。

    建议在使用该参数时,根据系统资源和浏览器的实际情况,适当地调整渲染进程数量的限制。

  • disable-features

    用于禁用某些浏览器功能。Chromium 浏览器中提供了许多功能和特性,有些用户可能不需要或者不喜欢某些功能,因此可以通过添加 disable-features 参数来禁用这些功能。

    该参数的语法为:–disable-features=[,,…]

    其中, 是要禁用的功能的名称,多个功能名称之间使用逗号分隔。

    例如,要禁用 Chromium 浏览器中的 JavaScript,可以使用以下命令:
    chrome --disable-features=JavaScript

    需要注意的是,禁用某些功能可能会影响浏览器的功能和性能,因此建议仅在必要情况下使用该参数,并根据实际情况选择要禁用的功能。

  • 更多可用命令可用看

    https://bitbucket.org/chromiumembedded/cef/src/master/libcef/common/cef_switches.cc

    https://bitbucket.org/chromiumembedded/cef/src/master/tests/shared/common/client_switches.cc

    https://peter.sh/experiments/chromium-command-line-switches/

5、Web部分关键代码👊👎😷🦠

  • hello.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>本地Html文件</title>
</head>
<body>

<h1 align="center" style="font-size:80px; color:red;">hello </h1>
<p align="center" style="font-size:70px; color:blue;">world</p>

</body>
</html>

6、源代码🐍🉐

. ஓ๑⸜💗⸝‍๑ஓ
 ᕬ ᕬ   ∧ ∧
(˵ㅇ◡ㅇ˵) (ᓀ ֊ ᓂ˵ )
(つ☕O O🍵⊂)

posted @   mahuifa  阅读(0)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示