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 GetBrowserProcessHandler()OVERRIDE;
    virtual CefRefPtr GetRenderProcessHandler()OVERRIDE;
    virtual void OnContextCreated(CefRefPtr browser, CefRefPtr frame, CefRefPtr context) OVERRIDE;
    virtual void OnWebKitInitialized() OVERRIDE;

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

class CV8JsHandler :
    public CefV8Handler
{
public:
    CV8JsHandler(void);
    CV8JsHandler(CefRefPtr 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 object,
        const CefV8ValueList& arguments,
        CefRefPtr& retval,
        CefString& exception) OVERRIDE;
private:
    CefString NullString = "";
    CefRefPtr 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

你可能感兴趣的:(成长之路)