CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目。Google Chromium项目主要是为Google Chrome应用开发的,而CEF的目标则是为第三方应用提供可嵌入浏览器支持。CEF隔离底层Chromium和Blink的复杂代码,并提供一套产品级稳定的API,发布跟踪具体Chromium版本的分支,以及二进制包。CEF的大部分特性都提供了丰富的默认实现,让使用者做尽量少的定制即可满足需求。在本文发布的时候,世界上已经有很多公司和机构采用CEF,CEF的安装量超过了100万。[CEF wikipedia]页面上有使用CEF的公司和机构的不完全的列表。CEF的典型应用场景包括:
CEF3是基于Chomuim Content API多进程构架的下一代CEF,拥有下列优势:
(摘取自https://github.com/fanfeilong/cefutil/blob/master/doc/CEF%20General%20Usage-zh-cn.md#request-interception ps:cef3官网的翻译文档)
cef_binary_3.2171.1972_windows32:VS2005-2010可直接编译版本,也不存在3.2171.1901的外边框问题,但是输入法点位有问题。(下载链接)
cef_binary_3.2623.1401_windows32,cef3最后一个支持XP系统的版本。(下载链接:cef3.2623.1395编译后文件)
其他编译版本支持MP3等可加群:231250586
CEF3的各个类的介绍我这就不写了,其他博客已经介绍的非常详细了,我这就直接开始说使用过程。先贴两个类:
#ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
#define CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
#include "include/cef_client.h"
#include "include/cef_base.h"
#include "include/cef_browser.h"
#include "include\base\cef_lock.h"
#include "include/cef_web_plugin.h"
#include "cef_cookie.h"
#include
class SimpleHandler : public CefClient,
public CefDisplayHandler,
public CefDownloadHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefContextMenuHandler,
public CefCookieVisitor,
public CefWebPluginInfoVisitor
{
public:
SimpleHandler();
~SimpleHandler();
// Provide access to the single global instance of this object.
static SimpleHandler* GetInstance();
// CefClient methods:
virtual CefRefPtr GetDisplayHandler() OVERRIDE {
return this;
}
virtual CefRefPtr GetLifeSpanHandler() OVERRIDE {
return this;
}
virtual CefRefPtr GetLoadHandler() OVERRIDE {
return this;
}
virtual CefRefPtrGetContextMenuHandler() {
return this;
}
virtual CefRefPtr GetDownloadHandler(){
return this;
}
// CefDisplayHandler methods:
virtual void OnTitleChange(CefRefPtr browser,
const CefString& title) OVERRIDE;
// CefLifeSpanHandler methods:
/*在创建新的浏览器之后调用;*/
virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE;
/*当浏览器收到请求关闭时调用;*/
virtual bool DoClose(CefRefPtr browser) OVERRIDE;
/*浏览器销毁之前调用;*/
virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE;
/*在创建新的弹出式浏览器IO线程之前调用;*/
/*本程序主要阻止弹出,在本浏览器中打开;*/
virtual bool OnBeforePopup(CefRefPtr browser,
CefRefPtr frame,
const CefString& target_url,
const CefString& target_frame_name,
WindowOpenDisposition target_disposition,
bool user_gesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr& client,
CefBrowserSettings& settings,
bool* no_javascript_access) OVERRIDE;
// CefLoadHandler methods:
/*浏览器加载错误时调用;*/
virtual void OnLoadError(CefRefPtr browser,
CefRefPtr frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
/*浏览器完成加载时调用;*/
virtual void OnLoadEnd(CefRefPtr browser,
CefRefPtr frame,
int httpStatusCode) OVERRIDE;
// CefDownloadHandler methods:
/*在下载开始之前调用;*/
virtual void OnBeforeDownload( CefRefPtrbrowser,
CefRefPtrdownload_item,
const CefString&suggested_name,
CefRefPtrcallback) OVERRIDE;
/*在下载状态或进度信息更新时调用;*/
virtual void OnDownloadUpdated( CefRefPtrbrowser,
CefRefPtrdownload_item,
CefRefPtrcallback) OVERRIDE;
// CefContextMenuHandler methods:
/*在显示上下文菜单之前调用;*/
virtual void OnBeforeContextMenu(CefRefPtr browser,
CefRefPtr frame,
CefRefPtr params,
CefRefPtr model) OVERRIDE;
/*调用来执行从上下文菜单中选择的命;*/
virtual bool OnContextMenuCommand(CefRefPtr browser,
CefRefPtr frame,
CefRefPtr params,
int command_id,
EventFlags event_flags) OVERRIDE;
// CefCookieVisitor methods:
virtual bool Visit(const CefCookie& cookie, int count, int total,
bool& deleteCookie)OVERRIDE
{
return false;
};
// Request that all existing browser windows close.
// void CloseAllBrowsers(bool force_close);
bool IsClosing() const { return is_closing_; }
CefRefPtr GetBrowser(){return m_browser;}
public:
CefRefPtr m_browser;
bool is_closing_;
// Include the default reference counting implementation.
protected:
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(SimpleHandler);
//由于CEF采用多线程架构,有必要使用锁和闭包来保证在多不同线程安全的传递数据。IMPLEMENT_LOCKING定义提供了Lock()和Unlock()方法以及AutoLock对象来保证不同代码块同步访问
IMPLEMENT_LOCKING(SimpleHandler);
//My members.
public:
//My variable
RECT m_ClientRc;//浏览器窗口大小;
int m_BrowserId;//浏览器ID唯一标识符;
CString m_name;
bool m_end;
CefWindowHandle m_main_wnd;//浏览器的父窗口句柄;
//My method
void InvokeDefaultBrowser(std::wstring url);//使用默认浏览器打开url;
int JugeIsAdvertisementWindow(CefString strUrl);//判断url类型;
void SetMainHwnd(CefWindowHandle hwnd);//获取浏览器的父窗口句柄;
void CloseHostBrowser(CefRefPtrbrowser, bool force_close) ;
//void SetDlg(AccountDlg *Dlg);
};
#endif // CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "simple_handler.h"
#include
#include
#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"
#include "client_switches.h"
#define MENU_ID_VIEW_DELETHC MENU_ID_USER_FIRST + 200
#define MENU_ID_VIEW_GOTSY MENU_ID_USER_FIRST + 202
#define WM_AFTER_BROSWER_CREATE WM_USER+0x1001
#define URL_Redirect 1
#define URL_DYZS 2
#define URL_OUTLIST 3
namespace {
SimpleHandler* g_instance = NULL;
} // namespace
SimpleHandler::SimpleHandler()
: is_closing_(false), m_browser(NULL) {
DCHECK(!g_instance);
g_instance = this;
m_main_wnd = NULL;
m_end=false;
memset(&m_ClientRc,0,sizeof(RECT));
}
SimpleHandler::~SimpleHandler() {
g_instance = NULL;
}
void SimpleHandler::SetMainHwnd(CefWindowHandle hwnd)
{
//AutoLock lock_scope(this);
m_main_wnd = hwnd;
}
// static
SimpleHandler* SimpleHandler::GetInstance() {
return g_instance;
}
void SimpleHandler::OnAfterCreated(CefRefPtr browser) {
CEF_REQUIRE_UI_THREAD();
if (!m_browser.get())
{
m_browser = browser;
m_BrowserId = browser->GetIdentifier();
}
else if (browser->IsPopup())
{
}
}
bool SimpleHandler::DoClose(CefRefPtr browser) {
CEF_REQUIRE_UI_THREAD();
if(m_browser)
is_closing_ = true;
// Allow the close. For windowed browsers this will result in the OS close
// event being sent.
return false;
}
void SimpleHandler::OnBeforeContextMenu(CefRefPtr browser, CefRefPtr frame,CefRefPtr params, CefRefPtr model)
{
// //在这里,我添加了自己想要的菜单;
cef_context_menu_type_flags_t flag = params->GetTypeFlags();
model->Clear();
if (flag & CM_TYPEFLAG_PAGE){
//普通页面的右键消息;
model->AddItem(MENU_ID_BACK, L"后退");
model->AddItem(MENU_ID_FORWARD, L"前进");
model->AddSeparator();
model->AddItem(MENU_ID_RELOAD, L"刷新");
model->AddItem(MENU_ID_VIEW_DELETHC, L"清理缓存");
}
}
bool SimpleHandler::OnContextMenuCommand(CefRefPtr browser, CefRefPtr frame, CefRefPtr params, int command_id, EventFlags event_flags)
{
//CefString strLinkURL;
CefString strURLLink;
CefString* strTargetURL = NULL;
int nBuffLength = 0;
switch (command_id)
{
case MENU_ID_VIEW_DELETHC:
if (true)
{
//外部程序实现
}
default:
break;
}
return false;
}
void SimpleHandler::CloseHostBrowser(CefRefPtrbrowser, bool force_close)
{
if (!CefCurrentlyOn(TID_UI))
{
// Execute on the UI thread.
CefPostTask(TID_UI, base::Bind(&SimpleHandler::CloseHostBrowser, this, browser, force_close));
return;
}
int nID = browser->GetIdentifier();
browser->GetHost()->CloseBrowser(force_close);
}
void SimpleHandler::OnBeforeClose(CefRefPtr browser) {
CEF_REQUIRE_UI_THREAD();
if (m_browser == NULL)
{
return;
}
if(m_browser->IsSame(browser))
m_browser = NULL;
}
void SimpleHandler::OnLoadError(CefRefPtr browser,
CefRefPtr frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) {
CEF_REQUIRE_UI_THREAD();
// Don't display an error for downloaded files.
if (errorCode == ERR_ABORTED)
return;
// Display a load error message.
std::stringstream ss;
ss << ""
"Failed to load URL " << std::string(failedUrl) <<
" with error " << std::string(errorText) << " (" << errorCode <<
").
";
frame->LoadString(ss.str(), failedUrl);
}
int SimpleHandler::JugeIsAdvertisementWindow(CefString strUrl)
{
if ((-1 != url.find(L"http")) ||
(-1 != url.find(L"https")))
{
return URL_Redirect;
}
return true;
}
void SimpleHandler::InvokeDefaultBrowser(std::wstring url)
{
::ShellExecuteW(NULL,L"open",url.c_str(), NULL, NULL, SW_NORMAL);
}
bool SimpleHandler::OnBeforePopup(CefRefPtr browser,
CefRefPtr frame,
const CefString& target_url,
const CefString& target_frame_name,
WindowOpenDisposition target_disposition,
bool user_gesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr& client,
CefBrowserSettings& settings,
bool* no_javascript_access)
{
std::wstring urlFind = target_url;
int iURL_type = JugeIsAdvertisementWindow(target_url);
if (iURL_type == URL_Redirect)//重定向
{
std::wstring url = target_url;
this->GetBrowser()->GetMainFrame()->LoadURL(url);
return true;
}
return false;
}
//文件下载方法重载
void SimpleHandler::OnBeforeDownload(CefRefPtrbrowser,CefRefPtr download_item,const CefString& suggested_name,CefRefPtrcallback)
{
callback->Continue( download_item ->GetURL(),true);
}
void SimpleHandler::OnDownloadUpdated(CefRefPtrbrowser,CefRefPtr download_item,CefRefPtrcallback)
{
// callback->Cancel();
CefString strUrl = download_item->GetURL();
// ShellExecute(NULL, L"open", strUrl.c_str(), NULL, NULL, SW_SHOW);
if(download_item->IsComplete())
{
//MessageBox.Show("下载成功");
if(browser->IsPopup()&&!browser->HasDocument())
{
//browser->GetHost()->ParentWindowWillClose();
//browser->GetHost()->CloseBrowser(true);
}
}
}
void SimpleHandler::OnLoadEnd(CefRefPtr browser,
CefRefPtr frame,
int httpStatusCode)
{
m_end = true;
}
void SimpleHandler::OnTitleChange(CefRefPtr browser,
const CefString& title)
{
CEF_REQUIRE_UI_THREAD();
CString strSendData(title.ToWString().c_str());
//获取页面标题
}
#pragma once
#include "stdafx.h"
#include "include\cef_app.h"
//#include "client_app.h"
class SimpleApp : public CefApp,
public CefBrowserProcessHandler,
public CefRenderProcessHandler
{
public:
SimpleApp();
~SimpleApp();
virtual CefRefPtr GetRenderProcessHandler() {
return this;
}
// CefApp methods:
virtual CefRefPtr GetBrowserProcessHandler() OVERRIDE;
/*提供了查看和修改之前的命令行参数的机会*/
virtual void OnBeforeCommandLineProcessing(const CefString& process_type,
CefRefPtr command_line) OVERRIDE;
// CefBrowserProcessHandler methods:
virtual void OnContextInitialized() OVERRIDE;
//CefRenderProcessHandler methods
/*在WebKit初始化之后调用;*/
/*注册JS方法;*/
virtual void OnWebKitInitialized() OVERRIDE;
/*在创建了一个对象的V8上下文之后立即调用;*/
/*注册JS方法;*/
virtual void OnContextCreated(CefRefPtr browser,
CefRefPtr frame,
CefRefPtr context) OVERRIDE;
private:
CefRefPtr v8Handler_;
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(SimpleApp);
private:
};
#include "simple_app.h"
SimpleApp::SimpleApp()
{
v8Handler_ = new CCEFV8HandlerEx;
}
SimpleApp::~SimpleApp()
{
//v8Handler_->Release();
}
CefRefPtr SimpleApp::GetBrowserProcessHandler()
{
return this;
}
void SimpleApp::OnBeforeCommandLineProcessing(const CefString & process_type, CefRefPtr command_line)
{
//设置中文语言环境
command_line->AppendSwitchWithValue("--lang", "zh-CN");//设置中文
//command_line->AppendSwitch("--enable-system-flash");//加载系统flash
// command_line->AppendSwitchWithValue("--ppapi-flash-version", "27.0.0.187");//加载文件夹内的flash
// // //加载flash插件
// command_line->AppendSwitchWithValue("--ppapi-flash-path", "plugins\\pepflashplayer32_27_0_0_187.dll");
}
void SimpleApp::OnContextInitialized()
{
Sleep(0);
}
void SimpleApp::OnWebKitInitialized()
{
//JS注册部分
std::string extensionCode =
"var app;"
"if (!app)"
" app = {};"
"(function() {"
" app.GetId = function() {"
" native function GetId();"
" return GetId();"
" };"
"})();";
// JavaScript里调用app.jsInvokeCPlusPlus时,就会去通过CefRegisterExtension注册的CefV8Handler列表里查找
// 找到"v8/app"对应的CCEFV8HandlerEx,就调用它的Execute方法
// 假设v8Handler_是SimpleApp的一个成员变量
//v8Handler_ = new CCEFV8HandlerEx();
bool bRet = CefRegisterExtension("v8/cloudAccountClient", extensionCode, v8Handler_);
}
void SimpleApp::OnContextCreated(CefRefPtr browser, CefRefPtr frame, CefRefPtr context)
{
OutputDebugString(_T("ClientAppRenderer::OnContextCreated, create window binding\r\n"));
// Retrieve the context's window object.
CefRefPtr object = context->GetGlobal();
CefRefPtr funcw = CefV8Value::CreateFunction("register",v8Handler_);//第一个参数和SetValue参数保持一致,否则无法调用
// Add the "register" function to the "window" object.
object->SetValue("register", funcw, V8_PROPERTY_ATTRIBUTE_NONE);
// Create the "NativeLogin" function.
CefRefPtr func = CefV8Value::CreateFunction("NativeLogin", v8Handler_);
// Add the "NativeLogin" function to the "window" object.
object->SetValue("NativeLogin", func, V8_PROPERTY_ATTRIBUTE_NONE);
}
通过函数bool CefInitialize(constCefMainArgs& args,
const CefSettings&settings,
CefRefPtr
void* windows_sandbox_info);
进行初始化,用户可以通过设置 settings来改变缓存路径,日志路径,单/多进程模式等等;代码如下:
void*sandbox_info = NULL;//Windows下可为null
CefMainArgsmain_args(AfxGetInstanceHandle());
CefRefPtrapp(new SimpleApp);// SimpleApp 继承了cefapp
CefSettingssettings;
settings.no_sandbox= true;
settings.multi_threaded_message_loop= true; //使用主程序消息循环
//settings.single_process= true; //使用单进程模式
TCHARszSpecialPath[MAX_PATH];
memset(szSpecialPath,'\0', sizeof(szSpecialPath));
//缓存路径;
CStringpath =L"C:\\Users\\Administrator\\AppData\\Cache";
_tcscpy(szSpecialPath,path); CefString(&settings.cache_path).FromString(szSpecialPath,sizeof(szSpecialPath) / 2, true);
CefString(&settings.log_file).FromString(szSpecialPath,sizeof(szSpecialPath) / 2, true);//日志
CefInitialize(main_args,settings, app.get(), sandbox_info);
通过函数bool CreateBrowser(constCefWindowInfo& windowInfo,
CefRefPtr
constCefString& url,
constCefBrowserSettings& settings,
CefRefPtr
CefWindowInfo windowInfo设置浏览器的窗口信息,如大小和父窗口句柄;
CefString url 创建的浏览器打开的连接;
CefBrowserSettings& settings, 初始化传入参数,CefRefPtr
创建代码:
CefWindowInfowindow_info;
RECTrt;
GetWindowRect(m_hWnd,&rt);
window_info.SetAsChild(m_hWnd,rt);//设置浏览器窗口大小和父窗口句柄
CefRefPtrm_handler;
m_handler= new SimpleHandler();
m_handler->SetMainHwnd(m_hWnd);
m_handler->m_ClientRc=rt;
CefBrowserSettingsbrowserSettings;
CefString(&browserSettings.default_encoding).FromASCII("UTF-8");
browserSettings.universal_access_from_file_urls= STATE_ENABLED;
std::stringurl;
url= "www.baidu.com";
CefBrowserHost::CreateBrowser(window_info,m_handler.get(), url, browserSettings, NULL);
HWND hWnd=GetHWND();//duilib 的窗口句柄
RECT rect;
HWND cefB_hwnd = ::FindWindowEx(hWnd, NULL, L"CefBrowserWindow", NULL); //cef的窗口句柄
switch( uMsg )
{
case WM_SIZE:
{
if (cefB_hwnd)
{
GetClientRect(hWnd, &rect);//获取窗口大小
int nWidth = rect.right - rect.left - 2;
int nHeight = rect.bottom - rect.top - 31;
::MoveWindow(cefB_hwnd,rect.left+1,rect.top+30, nWidth, nHeight, TRUE);//改变cef窗口大小
//::MoveWindow(cefB_hwnd,1, 29, LOWORD(lParam)-2, HIWORD(lParam), TRUE);
}
break;
}
通过cef命令行参数设置路径:
/*提供了查看和修改之前的命令行参数的机会*/
virtual voidOnBeforeCommandLineProcessing(const CefString& process_type,
CefRefPtr
重写 cefapp类中的OnBeforeCommandLineProcessing函数设置命令行,
代码如下:
void SimpleApp::OnBeforeCommandLineProcessing(const CefString &process_type, CefRefPtr command_line)
{
//设置中文语言环境
command_line->AppendSwitchWithValue("--lang","zh-CN");
//command_line->AppendSwitch("--disable-web-security");//关闭同源策略
//command_line->AppendSwitchWithValue("--ppapi-flash-version","27.0.0.183");
//加载flash插件
//command_line->AppendSwitchWithValue("--ppapi-flash-path","plugins\\pepflashplayer.dll");
}
如上图,修改右键菜单选项,需要重写CefContextMenuHandler类中的OnBeforeContextMenu和OnContextMenuCommand两个方法来实现;
OnBeforeContextMenu:右键后触发,可以清空,添加,删除右键菜单内的内容重写例子如下代码:
cef_context_menu_type_flags_tflag = params->GetTypeFlags();
model->Clear();
if (flag & CM_TYPEFLAG_PAGE){
//普通页面的右键消息;
model->AddItem(MENU_ID_BACK,L"后退");
model->AddItem(MENU_ID_FORWARD, L"前进");
model->AddSeparator();
model->AddItem(MENU_ID_RELOAD, L"刷新");
model->AddItem(MENU_ID_VIEW_DELETHC,L"清理缓存");}
OnContextMenuCommand处理右键菜单选中的命令,配合OnBeforeContextMenu可以实现自己想要的命令效果,如后面实现的清理缓存功能。
基于CEF开发应用时,可能会有URL请求处理的需求,比如HTTP下载或上传,此时可以利用CEF提供的类库来完成,而不必自己实现或引入其它第三方的类库缓存清理方法(来源网络)
可以用过继承修改CefURLRequestClient类进行封装实现,也可以直接调用该类,具体网上有很好的例子:
https://blog.csdn.net/foruok/article/details/50679694
在开发过程中,需求可能只允许一个窗口,这是就要将链接重定向到现在的窗口上
首先需要继承类:CefLifeSpanHandler,重写方法:OnBeforePopup。这个方法在创建新的弹出式浏览器IO线程之前调用,可以捕获到当前的url,然后GetBrowser()->GetMainFrame()->LoadURL(url);就可以在本窗口打开新的url。
补充,多标签页也可以通过这个方法实现,也可以吧捕获到的URL穿个本地默认的浏览器打开。
Cef3最有用的一个功能,就是js和c++交互。
C++调用JS比较简单,cef提供了函数,c++可以直接让界面执行js方法代码如下:
CefRefPtr
frame->ExecuteJavaScript("alert(\"c++呼叫JS \")",frame->GetURL(), 0);
c++执行上面两行代码时,浏览器就会弹框,显示内容“c++呼叫JS”,当然也可以执行其他的js,比如一些对表的填充操作。
JS调用C++比较复杂,浏览器在创建时需要通过CefRenderProcessHandler类中的两个方法在上下文中注册JS方法,在浏览器调用注册的JS方法时,回调到类CefV8Handler中的Execute方法,进行处理。具体实现代码:
void SimpleApp::OnWebKitInitialized()
{
//JS注册部分
std::string extensionCode =
"var app;"
"if (!app)"
" app = {};"
"(function(){"
" app.GetId = function() {"
" native function GetId();"
" return GetId();"
" };"
"})();";
// JvaScript里调用app.jsInvokeCPlusPlus时,就会去通过CefRegisterExtension注册的CefV8Handler列表里查找
// 找到"v8/app"对应的CCEFV8HandlerEx,就调用它的Execute方法
// 假设v8Handler_是SimpleApp的一个成员变量
//v8Handler_ = newCCEFV8HandlerEx();
bool bRet =CefRegisterExtension("v8/app", extensionCode, v8Handler_);
}
void SimpleApp::OnContextCreated(CefRefPtr
{
OutputDebugString(_T("OnContextCreated,create window binding\r\n"));
// Retrieve the context'swindow object.
CefRefPtr
CefRefPtr
// Add the"register" function to the "window" object.
object->SetValue("register", funcw,V8_PROPERTY_ATTRIBUTE_NONE);
}
OnWebKitInitialized()注册了一个js对象app,app有一个方法GetId();
OnContextCreated注册了一个js方法:register;
浏览器调用了js方法:app.Getid()或register()后:
bool CCEFV8HandlerEx::Execute(const CefString& name /*JavaScript调用的C++方法名字*/,
CefRefPtr object /*JavaScript调用者对象*/,
const CefV8ValueList&arguments /*JavaScript传递的参数*/, CefRefPtr& retval /*返回给JS的值设置给这个对象*/,
CefString& exception/*通知异常信息给JavaScript*/)
{
if(name.compare(CefString("register")) ==0) //测试
{
if (arguments.size() == 2&& arguments[0]->IsString() &&arguments[1]->IsFunction())
{
string strUrl =arguments[0]->GetStringValue();
CefRefPtrcallback = arguments[1];
CefV8ValueListarguments11;
arguments11.push_back(CefV8Value::CreateString("{\"eid\":\"\",\"message\":\"请登录\",\"status\":308}"));
// Execute thecallback.
callback->ExecuteFunction(NULL,arguments11);
}
return true;
}
else
{
OutputDebugString(_T("failed!\r\n"));
}
// Function does not exist.
return false;
}
在Execute方法中 执行c++代码,这样就实现了JS调用c++代码;
C++也可以通过ExecuteFunction(NULL, callback);回调参数给JS方法。
浏览器想要清理缓存,没有相关接口,只能通过删除缓存的文件来实现清理缓存的功能。
Cef3存的的坑还是很多的,本人还没踩全,在开发过程中遇到一些,现在说几点:
1. 判断cef是否启动:若是多进程的情况下,可以通过任务管理器来判断
2. Cef3如果是启动时崩溃,请看资源目录是否文件都齐全;在退出时崩溃,程序退出前,在释放了所有的Browser后就直接调用退出操作。
3. 开了多进程时,Render进程无法断点调试,可在初始化的时候用单进程模式:settings.single_process = true;
4. Cef加载的很慢时,查看是否开启了IE代理(网络正常的情况下)
5. 还有就是版本的问题CEF(2272)之前的版本存在输入法点位问题,cef3.2171.1901版本在改变窗口大小时会出现白色边框(亲测)
6. 页面上的一些请求需要自己post
7. Cef3有下载接口但是需要自己实现下载页面
8. …
第一次写:有不对的可以告诉我!