Qt6.2.2+libCef Demo

Qt 6.2.2 + libCef Demo

先看看效果如何:
Qt6.2.2+libCef Demo_第1张图片

1.如何集成

1.1 目录整理

在编译好libCef文件之后,我们需要对文件目录做一些整理。

  • libCef的include头文件
  • libCef编译的二进制文件
  • 自己的源码目录

使用vs2019创建Qt项目,这里我就略过。

最后目录格式如下所示:

│  QCefWindow.sln
│  QSimpleCef.vcxproj
│  QSimpleCef.vcxproj.filters
│  
├─bin
│  ├─debug
│  │  │  chrome_100_percent.pak
│  │  │  chrome_200_percent.pak
│  │  │  ...
│  │          
│  └─release
│      │  cef_sandbox.lib
│      │  chrome_100_percent.pak
│      │  chrome_200_percent.pak
│  	   │  ...
│              
├─include
│  │  cef_accessibility_handler.h
│  │  cef_api_hash.h
│  │  cef_string_visitor.h
│  │  ...
│  │       
├─res
│  │  app.manifest
│  │  qtwidgetsapplication1.qrc
│  │  
│  ├─images
│  └─ui
│          qtwidgetsapplication1.ui
│          
└─source
        main.cpp
        qtwidgetsapplication1.cpp
        qtwidgetsapplication1.h
        ...

2.重点代码解释

在这个简单的demo有几处重点需要解释下:

/**
 * 初始化QT以及CEF相关
 */
int init_qt_cef(int& argc, char** argv)
{
    const HINSTANCE h_instance = static_cast(GetModuleHandle(nullptr));

    CefMainArgs main_args(h_instance);
    CefRefPtr app(new SimpleApp); //CefApp实现,用于处理进程相关的回调。

    const int exit_code = CefExecuteProcess(main_args, nullptr, nullptr);
    if (exit_code >= 0)
    {
        return exit_code;
    }

	 // Parse command-line arguments for use in this method.
	 CefRefPtr command_line = CefCommandLine::CreateCommandLine();
	 command_line->InitFromString(::GetCommandLineW());

    // 设置配置
    CefSettings settings;
    settings.multi_threaded_message_loop = true; //多线程消息循环
    settings.log_severity = LOGSEVERITY_DEBUG; //日志
    settings.no_sandbox = true; //沙盒

    if (command_line->HasSwitch("enable-chrome-runtime")) {
        // Enable experimental Chrome runtime. See issue #2969 for details.
        settings.chrome_runtime = true;
    }
    bool result = CefInitialize(main_args, settings, app.get(), nullptr);

    return -1;
}

2.1 多进程架构

因为libCef是多进程架构,所以下面的这条语句就会进来多次。

比如:看我的机器上的进程
在这里插入图片描述这里的SimpleApp是个什么东西,文档解释说提供进程级别的回调。好,我也是看的一脸懵逼。不过我暂且不着急去理解,我想随着深入的去做,我后面在来解释。

CefRefPtr app(new SimpleApp); //CefApp实现,用于处理进程相关的回调。

const int exit_code = CefExecuteProcess(main_args, nullptr, nullptr);
if (exit_code >= 0)
{
	return exit_code;
}

2.2 消息循环设置

设置多线程消息循环,这样是为了让libCef可以集成到我们的Qt框架。

settings.multi_threaded_message_loop = true; //多线程消息循环

从这里可以发现一个很有趣的现象,那就是这个demo中会有两个UI线程。

  • libCef有自己的ui线程
  • Qt有自己的ui线程

所以如果你去看libCef的代码,你就会发现很多CefCurrentlyOn(TID_UI) 这种语句的判断,就是在检查是否是在libCef的UI 线程环境中。

如果不是就会Post Task过去,通知libCef UI线程去做。因为我们不能直接Qt的UI线程去修改libCef的UI,多线程操作UI是不安全的。

Tip:

这里我们使用了libCef的多线程消息循环,在最后libCef退出的时候,不能在调用 CefQuitMessageLoop()退出消息

2.3 日志的设置

日志的设置是非常重要的,我把它设置为DEBUG级别的。会在运行目录下生成一个debug.log文件。

settings.log_severity = LOGSEVERITY_DEBUG; //日志

2.4 沙盒

因为是MD模式编译,所以沙盒就没法用了。更多信息参考之前的文章

settings.no_sandbox = true; //沙盒

2.5 simple_hanler和simple_app

其实这两个类并不是我自己的写的,而是我从libCef中的Demo中直接复制过来的。

我们先看simple_handler.h从头文件来看,就是继承了各种父类,然后去重写它们的虚函数

比如:

CefClient提供访问Browser实例的回调接口

CefLifeSpanHandler对Browser生命周期(Browser Life Span),比如:browser create ,browser destory

CefDisplayHandler 对浏览器上面的ui变化,比如:title change, address change…

CefLoadHandler浏览器上面的加载状态的变化,比如:load start, load end, load error…

class SimpleHandler : public CefClient,
					  public CefDisplayHandler,
					  public CefLifeSpanHandler,
					  public CefLoadHandler

CefApp接口提供了不同进程的可定制回调函数,比如:渲染进程,GPU进程的回调事件

class SimpleApp : public CefApp, public CefBrowserProcessHandler 

这个暂且就解释到这里,随着后面的深入我在解释。

其实我个人感觉,如果只是在应用层借助libCef开发,我们主要做得事情就是继承各种class,实现虚函数,然后被框架调用。

说的简单点:就是实现各种回调函数

最后,我把源码 已经上传到gitee了,有兴趣的同学可以下载跑下看看效果。

项目地址:https://gitee.com/liushixiong/qcef-window

下一节,我会说明 Check failed: !IsCefShutdown(). Object reference incorrectly错误原因

你可能感兴趣的:(Qt6.2.2,+,libCef实战,qt,开发语言,c++)