CEF(Chromium Embedded Framework和JavaScript交互相互调用函数和设置数据

3.1     CEF和JavaScript交互

3.1.1     在CEF执行JavaScript脚本

3.1.2     窗口绑定方式实现CEF设置JavaScript的变量

3.1.3     扩展方式(Extension)实现CEF设置JavaScript的变量

3.1.4     窗口绑定方式实现CEF给JavaScript提供函数

3.1.5     Extension方式实现CEF给JavaScript提供函数

 

3.1  CEF和JavaScript交互

https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md

CEF使用的V8 JavaScript 引擎用于内部JavaScript实现,每一个frame都有JS上下文(context),为JS代码执行提供范围和安全。CEF暴露了很多JS特性可以和客户端程序进行交互。

3.1.1         在CEF执行JavaScript脚本

应用场景是需要在CEF中拦截一个URL请求,并把它重定向到另外一个URL,可以调用pFrame->ExecuteJavaScript来执行一个JavaScript脚本,实现跳转。当然也可以实现其他应用功能。

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

        std::string strurl = pFrame->GetURL().ToString();

        std::string strname = pFrame->GetName().ToString();

pFrame->GetName().ToString().c_str());

        if (pFrame->GetURL() == "https://10.19.141.75/portal/")

        {

                         pFrame->ExecuteJavaScript("var param= { url:'https://10.19.141.75/ishelf-web/personalCenter' }; \

                         window.goToApp(param);\

                     var paramEx = { isExtend:true };\

                     window.extendScreen(paramEx);\

                 ", pFrame->GetURL(), 0);

        }

3.1.2         窗口绑定方式实现CEF设置JavaScript的变量

在CEF程序中,创建一个CefV8Value对象,获取上下文的窗口对象,注入窗口对象一个变量值,网页中就可以使用JavaScript获取这个变量值。窗口绑定在CefRenderProcessHandler::OnContextCreated()函数中。是上下文创建响应函数,窗口绑定方式在每次frame重新加载(context创建)时都会加载一遍,CEF程序可以在OnContextCreated()给每一个frame设置不同的变量值。

    CefRefPtr<CefBrowser> browser,

    CefRefPtr<CefFrame> frame,

    CefRefPtr<CefV8Context> context) {

  // Retrieve the context's window object.

  CefRefPtr<CefV8Value> object = context->GetGlobal();

 

  // Create a new V8 string value. See the "Basic JS Types" section below.

  CefRefPtr<CefV8Value> str = CefV8Value::CreateString("My Value!");

 

  // Add the string to the window object as "window.myval". See the "JS Objects" section below.

  object->SetValue("myval", str, V8_PROPERTY_ATTRIBUTE_NONE);

}

JavaScript in the frame can then interact with the window bindings.

 

<script language="JavaScript">

alert(window.myval); // Shows an alert box with "My Value!"

</script>

3.1.3         扩展方式(Extension)实现CEF设置JavaScript的变量

Extension方式和窗口绑定方式类似,但是Extension方式是为每一个frame加载到上下文context,一旦加载变不能在修改,没有加载之前,DOM是不存在的,尝试范围这个值的DOM会出现崩溃。Extension方式是在CefRenderProcessHandler::OnWebKitInitialized()函数中用CefRegisterExtension() 函数注册的,是在初始化函数中实现的,所以对于每一个frame都是一样的。

void MyRenderProcessHandler::OnWebKitInitialized() {

  // Define the extension contents.

  std::string extensionCode =

    "var test;"

    "if (!test)"

    "  test = {};"

    "(function() {"

    "  test.myval = 'My Value!';"

    "})();";

 

  // Register the extension.

  CefRegisterExtension("v8/test", extensionCode, NULL);

}

JS中调用变量值

<script language="JavaScript">

alert(test.myval); // Shows an alert box with "My Value!"

</script>

3.1.4         窗口绑定方式实现CEF给JavaScript提供函数

(1)   自定义类实现CefV8Handler类,实现Execute接口,JavaScript执行函数后,会将函数名称、参数和返回值引用传递给Execute函数,Execute函数根据函数名去调用函数,函数的具体实现在Execute中,然后执行返回返回值。

class MyV8Handler : public CefV8Handler {

public:

  MyV8Handler() {}

 

  virtual bool Execute(const CefString& name,

                       CefRefPtr<CefV8Value> object,

                       const CefV8ValueList& arguments,

                       CefRefPtr<CefV8Value>& retval,

                       CefString& exception) OVERRIDE {

    if (name == "myfunc") {

      // Return my string value.

      retval = CefV8Value::CreateString("My Value!");

      return true;

    }

 

    // Function does not exist.

    return false;

  }

 

  // Provide the reference counting implementation for this class.

  IMPLEMENT_REFCOUNTING(MyV8Handler);

};

(2)将函数名称设置到窗口对象,提供接受调用的handle

void MyRenderProcessHandler::OnContextCreated(

    CefRefPtr<CefBrowser> browser,

    CefRefPtr<CefFrame> frame,

    CefRefPtr<CefV8Context> context) {

  // Retrieve the context's window object.

  CefRefPtr<CefV8Value> object = context->GetGlobal();

 

  // Create an instance of my CefV8Handler object.

  CefRefPtr<CefV8Handler> handler = new MyV8Handler();

 

  // Create the "myfunc" function.

  CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);

 

  // Add the "myfunc" function to the "window" object.

  object->SetValue("myfunc", func, V8_PROPERTY_ATTRIBUTE_NONE);

}

(3)JavaScript执行函数调用,就会进入Execute函数,返回返回值,alert会以弹窗形式展示结果。

<script language="JavaScript">
alert(window.myfunc()); // Shows an alert box with "My Value!"
</script>

 

3.1.5         Extension方式实现CEF给JavaScript提供函数

JavaScript调用CEF中的函数步骤:

(1)实现app类,继承与CefApp,重写OnWebKitInitialized,在OnWebKitInitialized函数内部使用字符串定义函数。CEF调用CefRegisterExtension函数向JavaScript注册函数,并提供处理调用的handler。

//CefClientApp.h

class CCefClientApp : public CefApp, public CefBrowserProcessHandler, CefRenderProcessHandler

{

public:

    CCefClientApp();

    ~CCefClientApp();

 

 

    //所有的CEF接口 都需要重载GetXXXHandler,并且return this,才会有效

    virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override { return this; }

 

    //===========CefRenderProcessHandler

    virtual void OnWebKitInitialized() override;

 

private:

    CefRefPtr<CCEFV8HandlerEx> v8Handler_;

    // Include the default reference counting implementation.

    IMPLEMENT_REFCOUNTING(CCefClientApp);

 

private:

 

};

 

//CefClientApp.cpp

 

void CCefClientApp::OnWebKitInitialized()

{

    //MessageBox(NULL,L"OnWebKitInitialized\n",0,0);

    std::string app_code =

        //-----------------------------------

        //声明JavaScript里要调用的Cpp方法

        "var app;"

        "if (!app)"

        "  app = {};"

        "(function() {"

 

        //  jsInvokeCPlusPlus 实例函数

        "  app.jsInvokeCPlusPlus = function(v1, v2) {"

        "    native function jsInvokeCPlusPlus();"

        "    return jsInvokeCPlusPlus(v1, v2);"

        "  };"

 

        //函数

        "  app.jsTransform = function(v1) {"

        "    native function jsTransform();"

        "    return jsTransform(v1);"

        "  };"

 

        "})();";

 

 

    // Register app extension module

 

    // JavaScript里调用app.jsInvokeCPlusPlus时,就会去通过CefRegisterExtension注册的CefV8Handler列表里查找

    // 找到"v8/app"对应的CCEFV8HandlerEx,就调用它的Execute方法

    // 假设v8Handler_是CCefClientApp的一个成员变量

    //v8Handler_ = new CCEFV8HandlerEx();

 

    CefRegisterExtension("v8/app", app_code, v8Handler_);

 

}

(2)JavaScript调用函数

<html>

<script>

app.jsInvokeCPlusPlus("123","xyz");

app.jsTransform("hello world");

</script>

</html>

(3)    handler的Execute函数接收调用响应,根据函数名称判断是调用哪个函数,获取参数调用函数。

//CEFV8HandlerEx.h
 
class CCEFV8HandlerEx : public CefV8Handler {
public:
    CCEFV8HandlerEx();
    ~CCEFV8HandlerEx();
public:
    virtual bool Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception) override;
private:
    // Map of message callbacks.
    typedef std::map<std::pair<std::string, int>, std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value> > >CallbackMap;
    CallbackMap callback_map_;
 
 
public:
    IMPLEMENT_REFCOUNTING(CCEFV8HandlerEx);
};
 
//CEFV8HandlerEx.cpp
 
//JS调用C++函数的回调
bool CCEFV8HandlerEx::Execute(const CefString& name  /*JavaScript调用的C++方法名字*/, CefRefPtr<CefV8Value> object /*JavaScript调用者对象*/, const CefV8ValueList& arguments /*JavaScript传递的参数*/, CefRefPtr<CefV8Value>& retval /*返回给JS的值设置给这个对象*/, CefString& exception/*通知异常信息给JavaScript*/)
{
    if (name == _T("jsInvokeCPlusPlus"))
    {
        if (arguments.size() == 2)
        {
            CefString strParam1 = arguments.at(0)->GetStringValue();
            CefString strParam2 = arguments.at(1)->GetStringValue();
 
            TCHAR szBuffer[512];
            StringCbPrintf(szBuffer, sizeof(szBuffer), _T("jsInvokeCPlusPlus(%s,%s)"), strParam1.c_str(), strParam2.c_str());
            ::MessageBox(GetForegroundWindow(), szBuffer, _T("jsInvokeCPlusPlus"), MB_OK);
            retval = CefV8Value::CreateInt(0);
        }
        else
        {
            retval = CefV8Value::CreateInt(2);
        }
 
        return true;
 
    }
 
    if (name == L"jsTransform") {
        CefString strParam1 = arguments.at(0)->GetStringValue();
        TCHAR szBuffer[512];
        StringCbPrintf(szBuffer, sizeof(szBuffer), _T("jsTransform(%s)"), strParam1.c_str());
        ::MessageBox(GetForegroundWindow(), szBuffer, _T("jsTransform"), MB_OK);
    }
    return false;
}

自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:

https://www.cnblogs.com/bclshuai/p/11380657.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bclshuai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值