文章目录
- 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需要通过原生窗口句柄(如HWND
或XWindow
)嵌入到Qt界面中。使用QWindow
的winId()
获取句柄:
#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资源文件(
locales
、swiftshader
)未正确复制到输出目录。 - 解决:在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浏览器组件。关键点包括:
- 正确配置CEF3的库和资源文件。
- 使用
QWidget::winId()
获取原生窗口句柄。 - 通过定时器驱动CEF3消息循环。
- 处理多进程架构。
如果需要更复杂的交互(如JavaScript调用C++函数),需进一步实现CefV8Handler
和CefRenderProcessHandler
接口。