cef3实现点击按钮弹出页面_Cef功能开发经验总结

本文详细介绍了Cef3在集成过程中的经验,包括CefApp接口、CefClient接口的使用,以及多线程消息循环的配置。着重讲解了C++与JavaScript的交互,以及离屏渲染的实现,同时讨论了多进程渲染和Cef在不同模式下的表现。文章最后提到了一些集成中遇到的问题和解决办法。
摘要由CSDN通过智能技术生成

这是我开发Cef功能时对踩过的坑,进行的总结,话说Cef坑真的不少。好在踩完后用起来还是挺爽的。最终的代码可以下载网易云信PC Demo点我跳转

资料准备

这是我集成过程中查到的一些资料,包括了Cef开发的各方面资料

在调试Cef时需要Cef的pdb和源码:

Cef基本结构

CefApp接口

CefApp接口提供了不同进程的可定制回调函数,每一个进程对应一个CefApp接口。CefBrowserProcessHandler对应浏览器进程的回调,CefRenderProcessHandler对应渲染进程的回调。我们应该继承CefApp、CefBrowserProcessHandler、CefRenderProcessHandler接口。如果完全使用多进程模式,可以分别在浏览器进程和渲染进程里分开继承接口

CefApp::OnBeforeCommandLineProcessing方法里可以附加传入给Cef的命令行参数,这里可以附加很多控制参数

CefRenderProcessHandler::OnWebKitInitialized方法可以在渲染进程初始化时用来注册js扩展代码,实现C++与JS交互

CefRenderProcessHandler::OnFocusedNodeChanged方法可以检测当前获取到焦点html元素,获取到一些元素信息可以通过进程通信发送给浏览器进程来辅助做进一步的判断

CefRenderProcessHandler::OnProcessMessageReceived方法用于接收浏览器进程发来的消息,在做C++与JS交互时会用到

CefClient接口

每一个CefBrowser对象会对应一个CefClient接口,用于处理浏览器页面的各种回调信息,包括了Browser的生命周期,右键菜单,对话框,状态通知显示,下载事件,拖曳事件,焦点事件,键盘事件,离屏渲染事件。随着Cef版本的更新这些接口也会扩展和更新,多数对Cef进行行为控制的方法都集中在这些接口,如果对Cef有新的功能需求,一般都可以先翻翻这些接口中有没有提供相关功能

CefClient::OnProcessMessageReceived方法用于接收渲染进程发到的消息,在做C++与JS交互时会用到

CefSettings结构体

CefSettings结构体定义了Cef的全局配置信息,比如指定单进程模式、指定渲染子进程路径、设置localstorage路径、设置日志等级、Cef资源文件路径。其中对于项目最重要的字段是single_process、multi_threaded_message_loop、windowless_rendering_enabled,分别用于指定单进程模式、多线程渲染模式、离屏渲染模式。

兼容现有的消息循环

如果是UI线程消息循环构架较简单的项目,可以直接调用CefRunMessageLoop来使用Cef自带的消息循环,它会阻塞线程直到调用了CefQuitMessageLoop函数,CefRunMessageLoop是兼容传统的Win32消息循环的。

不过NIM项目底层是使用谷歌base库的多线程构架,所以没法直接使用CefRunMessageLoop。(PS:实际上Cef的底层消息循环也是谷歌的base库)

要让NIM的消息循环兼容Cef消息循环,有两种方法。

第一种方法

第一种方法是使用CefDoMessageLoopWork函数代替CefRunMessageLoop来完全消息消息循环。CefDoMessageLoopWork函数的作用是让Cef执行一次消息循环,这个函数不会阻塞线程,所以需要在我们现有的消息循环里的适当情况下主动去调用CefDoMessageLoopWork函数,如果调用的太频繁会很消耗CPU,如果调用频率太低会导致Cef来不及处理内部消息,让Cef界面反映变慢,所以这个函数的调用时机很重要。

因为CefDoMessageLoopWork函数应该在原本的消息循环中调用,而base库的UI线程消息循环是封装好的。这里首先说一下定制base库消息循环的方法。在WinMain入口函数里调用UI消息循环的代码如下:

{

MainThread thread; // 创建主线程

thread.RunOnCurrentThreadWithLoop(nbase::MessageLoop::kUIMessageLoop); // 执行主线程循环

}

在RunOnCurrentThreadWithLoop方法的第二个参数里可以指定一个消息分派器指针dispatcher,dispatcher继承自nbase::Dispatcher。base库中的UI消息循环代码如下:

PreProcessMessage(msg);

if (state_->dispatcher)

{

if (!state_->dispatcher->Dispatch(msg))

state_->should_quit = true;

}

else

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

PostProcessMessage(msg);

如果我们指定了RunOnCurrentThreadWithLoop方法的第二个参数,就不会调用原本的消息循环了,所以可以在这个dispatcher里定制消息循环。我实现CefMessageLoopDispatcher类并重写Dispatch接口。

BOOL CefMessageLoopDispatcher::IsIdleMessage(const MSG* pMsg)

{

switch (pMsg->message)

{

case WM_MOUSEMOVE:

case WM_NCMOUSEMOVE:

case WM_PAINT:

return FALSE;

}

return TRUE;

}

bool CefMessageLoopDispatcher::Dispatch(const MSG &msg)

{

static BOOL bDoIdle = TRUE;

TranslateMessage(&msg);

DispatchMessage(&msg);

if (IsIdleMessage(&msg))

{

bDoIdle = TRUE;

}

while (bDoIdle && !::PeekMessage(const_cast(&

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值