wxWidgets嵌入CEF3,并实现JavaScript调用C++代码

由于项目选用了wxWidgets做图形界面,wx既然能和QT相提并论,自然是他的跨平台做的也相当的优秀,唯一的美中不足是资料太少。
好了废话不多说,言归正传。
我使用wxWidgets版本是3.0.2,在windows vs2013下做的项目,接下来是要移植到Mac 和Linux系统下的。
wx嵌入CEF3是参考了GitHub上的一个开源项目,也是wx官方论坛里的大神提供的,连接地址如下:
https://github.com/sjlamerton/wxWebViewChromium
参照着这个基本上把CEF嵌入到wx中是没有任何问题的,不过这个项目比较早了,编译过程中会有一个报错,这都是小错误,很好
解决。
错误类似于下面的:
error C2660: “CefExecuteProcess”: 函数不接受 2 个参数 D:\work\wxWebViewChromium-master\webview_chromium3.cpp
这是由于CEF的新版本的这些函数的参数列表发生了变化,加入了沙箱的支持,多加一个NULL参数就行了。
CEF嵌入成功之后由于项目中牵涉到了JavaScript与C++直接的通信。两种JavaScript调用C++的代码和C++执行js
1、C++调用JavaScript是非常的容易 就是代码中
wxWebViewChromium::RunScript(const wxString& javascript);的实现,这里是重新实现了wxWebView的RunScript函数,直接调
用CEF的ExecuteJavaScript()函数,具体可以参考源代码:

void wxWebViewChromium::RunScript(const wxString& javascript)

{
	
	CefRefPtr<CefBrowser> browser = m_clientHandler->GetBrowser();

	CefRefPtr<CefFrame> frame = browser->GetMainFrame();

	frame->ExecuteJavaScript(javascript.ToStdString(), "", 0);

}

2、JavaScript调用C++的代码稍微复杂一点
首先要自己实现两个类分别为:

class MyCefApp
	:public CefApp,
	public CefBrowserProcessHandler,
	public CefRenderProcessHandler
{
public:
	MyCefApp();
	virtual ~MyCefApp(){}
public:
	virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()OVERRIDE;
	virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler()OVERRIDE;
	virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) OVERRIDE;
	virtual void OnWebKitInitialized() OVERRIDE;

	void OnContextInitialized() OVERRIDE;
	void OnBeforeChildProcessLaunch(CefRefPtr<CefCommandLine> command_line) OVERRIDE;
	void OnRenderProcessThreadCreated(CefRefPtr<CefListValue> extra_info) OVERRIDE;
	void OnScheduleMessagePumpWork(int64 delay) OVERRIDE;
protected:
	IMPLEMENT_REFCOUNTING(MyCefApp);
private:
	//js要调用的C++函数的注册
	void RegistrationCFunc(CefRefPtr<CefBrowser> browser, CefRefPtr<CefV8Value> window, const CefString& FuncName);
};

class CV8JsHandler :
	public CefV8Handler
{
public:
	CV8JsHandler(void);
	CV8JsHandler(CefRefPtr<CefBrowser> browser);
	virtual ~CV8JsHandler(void);
	enum MessageType
	{
		FAST_REPLY_TYPE = 0,		//快捷回复
		REPLY_TYPE,					//回复
		REPLY_ALL_TYPE,				//回复全部
		FORWARD_TYPE,				//转发
		AS_ATTACHMENT_FORWARD_TYPE,	//作为附件转发
		UNKNOWN_TYPE,				//未知类型
	};
public:
	virtual bool Execute(const CefString& name,
		CefRefPtr<CefV8Value> object,
		const CefV8ValueList& arguments,
		CefRefPtr<CefV8Value>& retval,
		CefString& exception) OVERRIDE;
private:
	CefString NullString = "";
	CefRefPtr<CefBrowser> m_browser;
	void SendMyMessage(const CefString& messageContent, const CefString& Num,MessageType messageType);
	IMPLEMENT_REFCOUNTING(CV8JsHandler);
};

a、在MyCefApp类的MyCefApp::OnContextCreated函数中实现C++函数在JavaScript中的注册(也可以在MyCefApp::OnWebKitInitialized()中实现,是两种不同的方法我目前没有采用这一种,有兴趣的可以参照CEF官方文档实现),注册的时候需要使用下面介绍的CV8JsHandler的对象实现注册

b、要知道CEF的JavaScript使用的是V8引擎,而CV8JsHandler::Execute这个函数是V8的回调函数,当JavaScript调用C++代码的时候就会执行该回调函数,在该回调函数中通过函数名可以知道JS调用的是上一步注册的哪个C++函数。

c、关于MyCefApp类的使用是在wxWebViewChromium::StartUp函数里面,调用CefInitialize(args, settings, myApp, NULL);
其中myApp是MyCefApp的对象

经过以上三个步骤就能实现JavaScript调用C++的代码。

有什么不好的地方,还请大神指正。

以下是我封装好的类源码的地址,有需要的可以拿去用:
http://download.csdn.net/download/ellan_bm/10104752
该代码github地址
https://github.com/bm296672810/wxWebViewChromium.git
由于是三年前的代码,现在的CEF最新版本会有变化,只是实现基类里面的虚函数就行,等有空了再把最新的CEF编通过发布出来


版权声明:本文为Ellan_BM原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。