如何在C++ QT 程序中集成cef3开源浏览器组件去显示网页?

文章目录

      • 1. **准备工作**
        • 1.1 下载CEF3
        • 1.2 配置Qt项目
      • 2. **集成CEF3到Qt窗口**
        • 2.1 创建Qt窗口容器
        • 2.2 初始化CEF3
      • 3. **处理CEF3消息循环**
      • 4. **处理多进程架构**
      • 5. **完整代码示例**
        • `main.cpp`
      • 6. **常见问题**
        • 6.1 黑屏问题
        • 6.2 窗口嵌入失败
        • 6.3 多进程调试
      • 7.**Github源码参考**
      • 8.**参考博客**
      • 总结

在Qt C++程序中集成CEF3(Chromium Embedded Framework)以显示网页,需要以下步骤:


1. 准备工作

1.1 下载CEF3
  • 从CEF官方网站下载预编译的CEF3二进制包(选择Standard版本)。
  • 解压后,目录结构通常包含:
    cef_binary/
      ├── include/          # CEF头文件
      ├── Release/          # 动态库文件(.dll/.so)
      ├── Resources/        # 浏览器资源文件(如 locales、swiftshader)
      └── libcef_dll/       # CEF的C++包装库
    
1.2 配置Qt项目
  • 在Qt项目文件(.pro)中添加CEF3的依赖:
    # 指定CEF3头文件路径
    INCLUDEPATH += $$PWD/cef_binary/include
    
    # 添加CEF3库路径(根据平台选择)
    win32 {
        LIBS += -L$$PWD/cef_binary/Release -lcef -lcef_dll_wrapper
    }
    linux {
        LIBS += -L$$PWD/cef_binary/Release -lcef -lcef_dll_wrapper -lX11
    }
    
    # 复制CEF3资源文件到输出目录(避免运行时黑屏)
    QMAKE_POST_LINK += $$escape_expand(\n) cp -r $$PWD/cef_binary/Resources/* $$OUT_PWD/
    

2. 集成CEF3到Qt窗口

2.1 创建Qt窗口容器

CEF3需要通过原生窗口句柄(如HWNDXWindow)嵌入到Qt界面中。使用QWindowwinId()获取句柄:

#include <QMainWindow>
#include <QWindow>

class BrowserWindow : public QMainWindow {
    Q_OBJECT
public:
    BrowserWindow(QWidget* parent = nullptr) : QMainWindow(parent) {
        // 创建一个空白的QWidget作为浏览器容器
        QWidget* container = new QWidget(this);
        setCentralWidget(container);
        
        // 获取原生窗口句柄
        m_cefWindowHandle = (void*)container->winId();
    }

private:
    void* m_cefWindowHandle;  // 用于传递给CEF3的窗口句柄
};
2.2 初始化CEF3

CEF3需要在主进程初始化,并在子进程中处理渲染:

#include "include/cef_app.h"
#include "include/cef_client.h"

class SimpleBrowserClient : public CefClient, public CefLifeSpanHandler {
public:
    // 实现CefClient接口
    CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    // 创建浏览器窗口
    void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
        // 浏览器创建完成
    }

    IMPLEMENT_REFCOUNTING(SimpleBrowserClient);
};

// 初始化CEF3
int main(int argc, char* argv[]) {
    CefMainArgs args(argc, argv);
    CefSettings settings;
    settings.no_sandbox = true;  // 禁用沙箱(简化配置)

    // 初始化CEF
    CefInitialize(args, settings, nullptr, nullptr);

    // 启动Qt应用
    QApplication app(argc, argv);
    BrowserWindow window;
    window.show();

    // 创建浏览器实例
    CefWindowInfo window_info;
    window_info.SetAsChild((HWND)window.cefWindowHandle(), CefRect(0, 0, 800, 600));

    CefBrowserSettings browser_settings;
    CefRefPtr<SimpleBrowserClient> client(new SimpleBrowserClient);
    CefBrowserHost::CreateBrowser(window_info, client, "https://www.example.com", browser_settings, nullptr);

    // 运行Qt事件循环
    app.exec();

    // 关闭CEF
    CefShutdown();
    return 0;
}

3. 处理CEF3消息循环

CEF3需要定期处理消息循环,而Qt有自己的事件循环。在Qt中可以通过定时器驱动CEF3消息:

class BrowserWindow : public QMainWindow {
    Q_OBJECT
public:
    BrowserWindow(QWidget* parent = nullptr) : QMainWindow(parent) {
        // 创建一个定时器,每隔10ms处理CEF消息
        QTimer* timer = new QTimer(this);
        connect(timer, &QTimer::timeout, []() {
            CefDoMessageLoopWork();  // 处理CEF消息
        });
        timer->start(10);
    }
};

4. 处理多进程架构

CEF3默认使用多进程模型(主进程 + 子进程)。需要在程序启动时区分进程角色:

int main(int argc, char* argv[]) {
    CefMainArgs args(argc, argv);
    CefRefPtr<CefApp> app;

    // 判断是否是子进程
    if (CefExecuteProcess(args, app, nullptr) >= 0) {
        return 0;  // 子进程直接退出
    }

    // 主进程初始化
    CefSettings settings;
    settings.no_sandbox = true;
    CefInitialize(args, settings, app, nullptr);

    // ... Qt代码 ...
}

5. 完整代码示例

main.cpp
#include <QApplication>
#include <QTimer>
#include "include/cef_app.h"
#include "BrowserWindow.h"

int main(int argc, char* argv[]) {
    CefMainArgs args(argc, argv);
    CefRefPtr<CefApp> app;

    // 处理子进程
    if (CefExecuteProcess(args, app, nullptr) >= 0) {
        return 0;
    }

    // 初始化CEF
    CefSettings settings;
    settings.no_sandbox = true;
    CefInitialize(args, settings, app, nullptr);

    // 启动Qt应用
    QApplication qtApp(argc, argv);
    BrowserWindow window;
    window.show();

    // 处理CEF消息循环
    QTimer cefTimer;
    QObject::connect(&cefTimer, &QTimer::timeout, []() {
        CefDoMessageLoopWork();
    });
    cefTimer.start(10);

    int ret = qtApp.exec();

    // 关闭CEF
    CefShutdown();
    return ret;
}

6. 常见问题

6.1 黑屏问题
  • 原因:CEF3资源文件(localesswiftshader)未正确复制到输出目录。
  • 解决:在Qt项目文件中添加资源复制命令:
    QMAKE_POST_LINK += $$escape_expand(\n) cp -r $$PWD/cef_binary/Resources/* $$OUT_PWD/
    
6.2 窗口嵌入失败
  • 原因:未正确传递窗口句柄。
  • 解决:确保使用QWidget::winId()获取句柄,并在CEF中调用SetAsChild
6.3 多进程调试
  • 子进程调试:通过--type=renderer参数启动子进程调试。

7.Github源码参考

https://github.com/tishion/QCefView

8.参考博客

https://blog.csdn.net/LF__plus/article/details/137793277
https://blog.csdn.net/weixin_38416696/article/details/111044995
https://juejin.cn/post/6981077794507718692

总结

通过上述步骤,可以在Qt应用中集成CEF3浏览器组件。关键点包括:

  1. 正确配置CEF3的库和资源文件。
  2. 使用QWidget::winId()获取原生窗口句柄。
  3. 通过定时器驱动CEF3消息循环。
  4. 处理多进程架构。

如果需要更复杂的交互(如JavaScript调用C++函数),需进一步实现CefV8HandlerCefRenderProcessHandler接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/966141.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Redis】安装配置Redis超详细教程 / Linux版

Linux安装配置Redis超详细教程 安装redis依赖安装redis启动redis停止redisredis.conf常见配置设置redis为后台启动修改redis监听地址设置工作目录修改密码监听的端口号数据库数量设置redis最大内存设置日志文件设置redis开机自动启动 学习视频&#xff1a;黑马程序员Redis入门到…

[LeetCode]day16 242.有效的字母异位词

242. 有效的字母异位词 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的 字母异位词 示例 1: 输入: s "anagram", t "nagaram" 输出: true示例 2: 输入: s "rat"…

[MoeCTF 2022]baby_file

题目 <html> <title>Heres a secret. Can you find it?</title> <?phpif(isset($_GET[file])){$file $_GET[file];include($file); }else{highlight_file(__FILE__); } ?> </html> 读取flag /?filephp://filter/readconvert.base64-encode…

Centos挂载镜像制作本地yum源,并补装图形界面

内网环境centos7.9安装图形页面内网环境制作本地yum源 上传镜像到服务器目录 创建目录并挂载镜像 #创建目录 cd /mnt/ mkdir iso#挂载 mount -o loop ./CentOS-7-x86_64-DVD-2009.iso ./iso #前面镜像所在目录&#xff0c;后面所挂载得目录#检查 [rootlocalhost mnt]# df -h…

判断您的Mac当前使用的是Zsh还是Bash:echo $SHELL、echo $0

要判断您的Mac当前使用的是Zsh还是Bash&#xff0c;可以使用以下方法&#xff1a; 查看默认Shell: 打开“终端”应用程序&#xff0c;然后输入以下命令&#xff1a; echo $SHELL这将显示当前默认使用的Shell。例如&#xff0c;如果输出是/bin/zsh&#xff0c;则说明您使用的是Z…

python 小游戏:扫雷

目录 1. 前言 2. 准备工作 3. 生成雷区 4. 鼠标点击扫雷 5. 胜利 or 失败 6. 游戏效果展示 7. 完整代码 1. 前言 本文使用 Pygame 实现的简化版扫雷游戏。 如上图所示&#xff0c;游戏包括基本的扫雷功能&#xff1a;生成雷区、左键点击扫雷、右键标记地雷、显示数字提示…

【重新认识C语言----文件管理篇】

目录 ​编辑 -----------------------------------------begin------------------------------------- 引言 1. 文件的基本概念 2. 文件指针 3. 文件的打开与关闭 3.1 打开文件 3.2 关闭文件 4. 文件的读写操作 4.1 读取文件 4.1.1 使用fgetc()读取文件 4.1.2 使用fg…

EasyExcel 导出合并层级单元格

EasyExcel 导出合并层级单元格 一、案例 案例一 1.相同订单号单元格进行合并 合并结果 案例二 1.相同订单号的单元格进行合并2.相同订单号的总数和总金额进行合并 合并结果 案例三 1.相同订单号的单元格进行合并2.相同订单号的商品分类进行合并3.相同订单号的总数和总金额…

WPF 进度条(ProgressBar)示例一

本文讲述&#xff1a;WPF 进度条(ProgressBar)简单的样式修改和使用。 进度显示界面&#xff1a;使用UserControl把ProgressBar和进度值以及要显示的内容全部组装在UserControl界面中&#xff0c;方便其他界面直接进行使用。 <UserControl x:Class"DefProcessBarDemo…

LabVIEW自定义测量参数怎么设置?

以下通过一个温度采集案例&#xff0c;说明在 LabVIEW 中设置自定义测量参数的具体方法&#xff1a; 案例背景 ​ 假设使用 NI USB-6009 数据采集卡 和 热电偶传感器 监测温度&#xff0c;需自定义以下参数&#xff1a; 采样率&#xff1a;1 kHz 输入量程&#xff1a;0~10 V&a…

新能源产业的质量革命:六西格玛培训如何重塑制造竞争力

在新能源行业狂飙突进的今天&#xff0c;企业若想在全球供应链中占据高地&#xff0c;仅靠技术突破已远远不够。制造效率的毫厘之差&#xff0c;可能成为市场话语权的千里之距。某光伏巨头曾因电池片良率低于行业均值1.5%&#xff0c;导致年损失超2.3亿元——这恰恰印证了六西格…

(11)gdb 笔记(4):设置执行方向 set exec-direction,

&#xff08;28&#xff09;引入 record 后&#xff0c;可以 设置执行方向 set exec-direction &#xff1a; 实践&#xff1a; &#xff08;29&#xff09; &#xff08;33&#xff09; 谢谢

redis持久化理论

0 前言 什么是持久化 redis操作都是在内存中&#xff0c;如果出现宕机的话&#xff0c;数据将不复存在&#xff0c;所以持久化是将内存中的数据刷盘到磁盘中&#xff0c;redis可以提供RDB和AOF将数据写入磁盘中。 一 持久化技术 本章节将介绍持久化RDB和AOF两个技术&#xf…

25/2/7 <机器人基础>雅可比矩阵计算 雅可比伪逆

雅可比矩阵计算 雅可比矩阵的定义 假设我们有一个简单的两个关节的平面机器人臂&#xff0c;其末端执行器的位置可以表示为&#xff1a; 其中&#xff1a; L1​ 和 L2 是机器人臂的长度。θ1​ 和 θ2是关节的角度。 计算雅可比矩阵 雅可比矩阵 JJ 的定义是将关节速度与末…

鸿蒙UI(ArkUI-方舟UI框架)- 使用文本

返回主章节 → 鸿蒙UI&#xff08;ArkUI-方舟UI框架&#xff09; 文本使用 文本显示 (Text/Span) Text是文本组件&#xff0c;通常用于展示用户视图&#xff0c;如显示文章的文字内容。Span则用于呈现显示行内文本。 创建文本 string字符串 Text("我是一段文本"…

科技赋能数字内容体验的核心技术探索

内容概要 在数字化时代&#xff0c;科技的迅猛发展为我们的生活和工作带来了深刻的变革。数字内容体验已经成为人们获取信息和娱乐的重要途径&#xff0c;而这背后的技术支持则扮演着至关重要的角色。尤其是在人工智能、虚拟现实和区块链等新兴技术的推动下&#xff0c;数字内…

详细教程 | 如何使用DolphinScheduler调度Flink实时任务

Apache DolphinScheduler 非常适用于实时数据处理场景&#xff0c;尤其是与 Apache Flink 的集成。DolphinScheduler 提供了丰富的功能&#xff0c;包括任务依赖管理、动态调度、实时监控和日志管理&#xff0c;能够有效简化 Flink 实时任务的管理和部署。通过 DolphinSchedule…

棋盘(二维差分)

题目&#xff1a; 5396. 棋盘 题目 提交记录 讨论 题解 视频讲解 小蓝拥有 nnnn 大小的棋盘&#xff0c;一开始棋盘上全都是白子。 小蓝进行了 mm 次操作&#xff0c;每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色&#xff0c;黑色棋子变…

MySQL数据库基础(创建/删除 数据库/表)

一、数据库的操作 1.1 显示当前数据库 语法&#xff1a;show databases&#xff1b; <1>show 是一个关键字&#xff0c;表示要执行的操作类型 <2>databases 是复数&#xff0c;表示显示所有数据库 上面的数据库中&#xff0c;除了java113&#xff0c;其它的数据库…

【WebLogic】Oracle发布WebLogic 14c最新版本-14.1.2.0

根据Oracle官方产品经理的博客&#xff0c;Oracle于2024年12月20日正式对外发布了WebLogic 14c的第二个正式版本&#xff0c;版本号为 14.1.2.0.0 &#xff0c;目前官方已开放客户端下载。该版本除继续支持 Jakarta EE 8 版本外&#xff0c;还增加了对 Java SE 17&#xff08;J…