当前位置: 首页 > article >正文

如何在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接口。


http://www.kler.cn/a/538472.html

相关文章:

  • 物联网软件开发与应用方向应该怎样学习,学习哪些内容,就业方向是怎样?(文末领取整套学习视频,课件)物联网硬件开发与嵌入式系统
  • 解决基于FastAPI Swagger UI的文档打不开的问题
  • 寒假2.7
  • 基于微信小程序的医院预约挂号系统的设计与实现
  • 第26场蓝桥入门赛
  • jupternote book出现闪退
  • Java爬虫:打造高效的数据抓取利器——详解详情接口设计与实现
  • The First项目报告:从NFT到动漫文化,ANIME的原创衍生IP
  • 如何清理浏览器一段时间以前的缓存
  • Git 冲突解决技巧与实践
  • FPGA高端项目:图像采集+UltraScale GTH光编码+UDP图传架构,高速接口转网络视频传输,提供工程源码和技术支持
  • 支持多种网络数据库格式的自动化转换工具——VisualXML
  • 25/2/7 <机器人基础>雅可比矩阵计算 雅可比伪逆
  • 协议-WebRTC-HLS
  • 08vue3实战-----在vue3项目中集成Element-Plus组件库
  • 保姆级教程--DeepSeek部署
  • snort的学习记录
  • 【自学笔记】文言一心的基础知识点总览-持续更新
  • Ollama下载安装教程
  • 从零开始玩转Docker:轻松开启容器化之旅
  • 关于32位和64位程序的传参方法及虚拟机调试工具总结
  • Linux提供给我们的定时器
  • 【k8s集群应用】kubenetes-YAML
  • QT实现多线程的方法
  • 谷歌浏览器多开指南:如何完成独立IP隔离?
  • 在线免费 HTML 预览导出为图片,并且支持水平切割