CEF的一些坑

首页 / C++ / 正文

获取中...

最近做了cef的离屏渲染,从未接触cef到做完这个功能,将近2周时间,遇到的坑mark一下,防止后人踩坑
有关cef的搭建可以看我这篇帖子: windows下CEF3 搭建

注意:离屏渲染对编程人员的GDI的基础颇有要求,如果你不熟悉GDI等需要去补习一下此类知识点,网上能找到离屏渲染的能用的资料很少,你也可以问我要一份写好的

官网的例子渲染使用OpenGL,我是用GDI实现,倒并不是觉得官方的不行,只是官方的写的看起来费劲,毕竟老外的编程思维真是很难看懂,就干脆自己实现了一份

离屏渲染的性能还是没有原窗口的好,所以万不得已还是别用这个方式,在编写渲染代码的时候,也要注意性能上的优化否则你的画面会变的卡卡的,尤其是如果你还需要视频播放的时候

1.CreateMutexA 不兼容,如果你用CreateMutexA 来确保防止重复运行的话还是另想办法吧,因为CEF是多进程,如果你非得用他来防止多开的话,可以在CefInitialize 执行之后在去使用它

2.编译的时候不要选择 use_sanbox(如果你需要用到他就勾选 否则会出很多编译错误)

3.cef是多进程的,browser跟render 之间不能用传统的C++的方式传递变量,要使用他内部的通讯方式

4.如果使用离屏渲染,GetViewRect 这个方法返回的rect很重要,如果返回的rect跟实际不一致会导致渲染失败,他的症状表现为启动后有进程但无法看到界面,所以遇到此类问题可以先去看看是否是这个原因导致

5.cef跟windowsx.h 头文件是不兼容的,避开他使用,如果必须用到windowsx.h里的东西,那就自己拿出来定义后使用 (目前只能这样没有办法 等后面看看cef官方是否会兼容这个头文件)

6.离屏渲染需要自己实现gdi画图,官方例子是使用OpenGL,不管用哪一种,需要对view跟pop都进行渲染以及擦掉渲染,cef有2类窗口,一类是主窗口view,另一个是pop弹窗,网页的下拉框也属于弹窗的一种,他弹出后的窗口也需要对他捕获渲染,要分开处理,否则会出现弹出的窗口不显示的情况,另外等他弹出窗口关闭后,还需要进行渲染擦除,不然会有残留(离屏渲染是真的麻烦)

    virtual void OnPaint(CefRefPtr<CefBrowser> browser,
        PaintElementType type,
        const RectList& dirtyRects,
        const void* buffer,
        int width,
        int height) OVERRIDE;

PaintElementType type 可以用来区分当前执行渲染的是哪一类窗口

然后你还需要实现这2个虚函数

    virtual void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
    virtual void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) OVERRIDE

在OnPopupShow中可以判断当前的弹窗的状态,用来选择是擦去渲染还是执行渲染弹出

在OnPopupSize中可以获取到弹出层的尺寸,可以联合OnPopupShow一起判断,其实在OnPaint中多少也能预知,因为离屏渲染大部分窗口都是不可调整,所以基本上尺寸如果变动就属于弹窗的一种了

7.如果他提示跨域拦截,要解决CEF的跨域问题,在 OnBeforeCommandLineProcessing 里增加一下代码

    virtual void OnBeforeCommandLineProcessing(
        const CefString& process_type,
        CefRefPtr<CefCommandLine> command_line) 
    {    
        command_line->AppendSwitch("--disable-web-security");
        command_line->AppendSwitch("--disable-site-isolation-trials");

        
    }

友情提示:OnBeforeCommandLineProcessing 属于CefApp,就是你最后要放到CefExecuteProcess 这里去当入参的这个类

8.cef中开启调试器的代码:

        CefWindowInfo windowInfo;
        CefBrowserSettings settings;
        windowInfo.SetAsPopup(NULL, "DevTools");
        m_browser->GetHost()->ShowDevTools(windowInfo, this, settings, CefPoint());

ps:直接拷贝我的代码,自己改下对象指针

9.屏蔽cef的自身右键菜单,代码如下

//屏蔽自身cef的菜单
void Client::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
    CefRefPtr<CefFrame> frame,
    CefRefPtr<CefContextMenuParams> params,
    CefRefPtr<CefMenuModel> model)
{
    CEF_REQUIRE_UI_THREAD();
    if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0)
    {
        if (model->GetCount() > 0)
        {
            model->Clear();
        }
    }
}

本来还想写下cef跟js的交互,但是发现好麻烦,东西蛮多。懒得整理了就酱了

CEF中的坑很多,各位慢慢踩,嘿嘿

打赏
评论区
头像
    头像
    Ming
    2024年1月20日 13:57
    回复