zoukankan      html  css  js  c++  java
  • Duilib嵌入CEF以及JavaScript与C++交互

    转载:http://blog.csdn.net/foruok/article/details/50573612

    转载:http://blog.csdn.net/foruok/article/details/50584985

    转载:http://blog.csdn.net/mfcing/article/details/44539035

    转载:https://github.com/fanfeilong/cefutil/blob/master/doc/CEF_JavaScript_Cpp.md

    转载:https://blog.csdn.net/aseseven/article/details/79482515(CEF3加载本地HTML文件时中文路径乱码的问题解决办法)

    转载:https://blog.csdn.net/u012778714/article/category/7003599

    JS与Native代码交互,是在Render进程中,所以我们要实现CefRenderProcessHandler接口

    一、JS 调用 C++

    • JavaScript注册函数给Render进程,Render进程保存该JavaScript函数
    • Render进程发消息通知Browser进程
    • Browser进程处理后,回发消息给Render进程
    • Render进程调用之前保存的JavaScript函数

    1.带参数没有返回值

    自己的APP类要继承于CefRenderProcessHandler

     1 #ifndef _CEFBROWSERAPP_H_
     2 #define _CEFBROWSERAPP_H_
     3 #include "include/cef_app.h"
     4 #include "CEFV8HandlerEx.h"
     5 
     6 class CCefBrowserApp
     7     : public CefApp
     8     , public CefBrowserProcessHandler
     9     , public CefRenderProcessHandler
    10 {
    11 public:
    12     CCefBrowserApp();
    13 
    14     virtual ~CCefBrowserApp();
    15 
    16 public:
    17     virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()OVERRIDE { return this; };
    18 
    19 public:
    20     // CefBrowserProcessHandler methods:
    21     virtual void OnContextInitialized();
    22 
    23     //CefRenderProcessHandler methods
    24     virtual void OnWebKitInitialized();
    25 
    26     CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE{ return this; }
    27 
    28     virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context);
    29 
    30     virtual void OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context);
    31 
    32 protected:
    33 
    34     CefRefPtr<CCEFV8HandlerEx> m_v8Handler;
    35 
    36     IMPLEMENT_REFCOUNTING(CCefBrowserApp);
    37 };
    38 #endif //_CEFBROWSERAPP_H_

    .cpp

     1 #include "CefBrowserApp.h"
     2 #include "stdafx.h"
     3 
     4 
     5 CCefBrowserApp::CCefBrowserApp()
     6     :m_v8Handler(new CCEFV8HandlerEx)
     7 {
     8 }
     9 
    10 CCefBrowserApp::~CCefBrowserApp()
    11 {
    12 }
    13 
    14 
    15 void CCefBrowserApp::OnContextInitialized()
    16 {
    17     // do nothing here, because we will create browser in my own dialog
    18 }
    19 
    20 void CCefBrowserApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
    21                               CefRefPtr<CefFrame> frame,
    22                               CefRefPtr<CefV8Context> context)
    23 {
    24     // Retrieve the context's window object.
    25     CefRefPtr<CefV8Value> object = context->GetGlobal();
    26 
    27     // Create the "NativeLogin" function.
    28     CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("NativeLogin", m_v8Handler);
    29 
    30     // Add the "NativeLogin" function to the "window" object.
    31     object->SetValue("NativeLogin", func, V8_PROPERTY_ATTRIBUTE_NONE);
    32 }
    33 
    34 void CCefBrowserApp::OnWebKitInitialized()
    35 {
    36     std::string app_code =
    37         "var app;" 
    38         "if (!app)"
    39         "    app = {};"
    40         "(function() {"
    41         "    app.GetId = function() {"
    42         "        native function GetId();"
    43         "        return GetId();"
    44         "    };"
    45         "})();";
    46 
    47     // Registered Javascript Function, which will be called by Cpp
    48     "  app.registerJavascriptFunction = function(name,callback) {"
    49         "    native function registerJavascriptFunction();"
    50         "    return registerJavascriptFunction(name,callback);"
    51         "  };"
    52 
    53         "})();";
    54 
    55 
    56     CefRegisterExtension("v8/app", app_code, m_v8Handler);//第一个参数不能为空,否则报错,这个名字可以自定义
    57 }

    注:CefRegisterExtension的注释
    // Example JavaScript extension code:
    // <pre>
    //   // create the 'example' global object if it doesn't already exist.
    //   if (!example)
    //     example = {};
    //   // create the 'example.test' global object if it doesn't already exist.
    //   if (!example.test)
    //     example.test = {};
    //   (function() {
    //     // Define the function 'example.test.myfunction'.
    //     example.test.myfunction = function() {
    //       // Call CefV8Handler::Execute() with the function name 'MyFunction'
    //       // and no arguments.
    //       native function MyFunction();
    //       return MyFunction();
    //     };
    //     // Define the getter function for parameter 'example.test.myparam'.
    //     example.test.__defineGetter__('myparam', function() {
    //       // Call CefV8Handler::Execute() with the function name 'GetMyParam'
    //       // and no arguments.
    //       native function GetMyParam();
    //       return GetMyParam();
    //     });
    //     // Define the setter function for parameter 'example.test.myparam'.
    //     example.test.__defineSetter__('myparam', function(b) {
    //       // Call CefV8Handler::Execute() with the function name 'SetMyParam'
    //       // and a single argument.
    //       native function SetMyParam();
    //       if(b) SetMyParam(b);
    //     });
    //
    //     // Extension definitions can also contain normal JavaScript variables
    //     // and functions.
    //     var myint = 0;
    //     example.test.increment = function() {
    //       myint += 1;
    //       return myint;
    //     };
    //   })();
    // </pre>
    // Example usage in the page:
    // <pre>
    //   // Call the function.
    //   example.test.myfunction();
    //   // Set the parameter.
    //   example.test.myparam = value;
    //   // Get the parameter.
    //   value = example.test.myparam;
    //   // Call another function.
    //   example.test.increment();
    // </pre>
    ///
    58 
    59 void CCefBrowserApp::OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
    60 {
    61     m_v8Handler = nullptr;
    62 }

    OnContextCreated给window对象绑定了一个NativeLogin函数,这个函数将由ClientV8Handler类来处理,当HTML中的JS代码调用window.NativeLogin时,ClientV8Handler的Execute方法会被调用。

    OnWebKitInitialized注册了一个名为app的JS扩展,在这个扩展里为app定义了GetId方法,app.GetId内部调用了native版本的GetId()。HTML中的JS代码可能如下:

    alert(app.GetId());

    当浏览器执行上面的代码时,CCEFV8HandlerEx的Execute方法会被调用,现在来看CCEFV8HandlerEx的实现

    .h

     1 #ifndef _CEFV8HANDLEREX_H_
     2 #define _CEFV8HANDLEREX_H_
     3 
     4 #include "include/cef_v8.h"
     5 
     6 class CCEFV8HandlerEx : public CefV8Handler {
     7 public:
     8     CCEFV8HandlerEx();
     9 
    10     ~CCEFV8HandlerEx();
    11 public:
    12     virtual bool Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception) override;
    13 private:
    14     // Map of message callbacks.
    15     typedef std::map<std::pair<std::string, int>, std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value> > >CallbackMap;
    16     CallbackMap callback_map_;
    17 
    18 protected:
    19     IMPLEMENT_REFCOUNTING(CCEFV8HandlerEx);
    20 };
    21 #endif//_CEFV8HANDLEREX_H_

    .cpp

     1 #include "CEFV8HandlerEx.h"
     2 #include "stdafx.h"
     3 #include <strsafe.h>
     4 
     5 CCEFV8HandlerEx::CCEFV8HandlerEx()
     6 {
     7 
     8 }
     9 
    10 CCEFV8HandlerEx::~CCEFV8HandlerEx()
    11 {
    12     // Remove any JavaScript callbacks registered for the context that has been released.
    13     if (!callback_map_.empty()) {
    14         CallbackMap::iterator it = callback_map_.begin();
    15         for (; it != callback_map_.end();) {
    16             if (it->second.first->IsSame(it->second.first))
    17                 callback_map_.erase(it++);
    18             else
    19                 ++it;
    20         }
    21     }
    22 }
    23 
    24 
    25 bool CCEFV8HandlerEx::Execute(const CefString& name  /*JavaScript调用的C++方法名字*/, CefRefPtr<CefV8Value> object /*JavaScript调用者对象*/, const CefV8ValueList& arguments /*JavaScript传递的参数*/, CefRefPtr<CefV8Value>& retval /*返回给JS的值设置给这个对象*/, CefString& exception/*通知异常信息给JavaScript*/)
    26 {
    27     if (name == "NativeLogin") 
    28     {//Window Binding
    29         if (arguments.size() == 2)
    30         {
    31             CefString strUser = arguments.at(0)->GetStringValue();
    32             CefString strPassword = arguments.at(1)->GetStringValue();
    33 
    34             //TODO: doSomething() in native way
    35 
    36             CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("login_msg");
    37 
    38             // Retrieve the argument list object.
    39             CefRefPtr<CefListValue> args = msg->GetArgumentList();
    40 
    41             // Populate the argument values.
    42             args->SetSize(2);
    43             args->SetString(0, strUser);
    44             args->SetString(1, strPassword);
    45 
    46             // Send the process message to the browser process.
    47             CefV8Context::GetCurrentContext()->GetBrowser()->SendProcessMessage(PID_BROWSER, msg);
    48 
    49 
    50 
    51             retval = CefV8Value::CreateInt(0);//函数的返回值 我们可以拿这个返回值做判断或者其他操作
    //var result = window.NativeLogin(document.getElementById("userName").value, document.getElementById("password").value);
    //document.getElementById("text").innerHTML = result
    52         }
    53         else
    54         {
    55             retval = CefV8Value::CreateInt(2);
    56         }
    57         return true;
    58     }
    59     else if (name == "GetId") 
    60     {//JS Extensions
    61         if (arguments.size() == 0) 
    62         {
    63             // execute javascript 
    64             // just for test
    65             CefRefPtr<CefFrame> frame = CefV8Context::GetCurrentContext()->GetBrowser()->GetMainFrame();
    66             frame->ExecuteJavaScript("alert('Hello, I came from native world.')", frame->GetURL(), 0);
    67 
    68             // return to JS
    69             retval = CefV8Value::CreateString("72395678");
    70             return true;
    71         }
    72     }
    73     // Function does not exist.
    74     return false;
    75 }

    在Browser进程中接受Render进程发过来的消息

    重写 virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process,CefRefPtr<CefProcessMessage> message);这个虚函数

    我把C++函数都写在了窗口类中,所以我对CCefBrowserEventHandler做了修改,把窗口指针传到Browser中,方便调用

    .h

     1 #ifndef _CEFBROWSEREVENTHANDLER_H_
     2 #define _CEFBROWSEREVENTHANDLER_H_
     3 #include "include/cef_client.h"  
     4 #include "include/base/cef_lock.h" //线程安全
     5 
     6 
     7 class CMainFrameWnd;
     8 
     9 class CCefBrowserEventHandler
    10     : public CefClient
    11     , public CefDisplayHandler            // 显示变化事件
    12     , public CefLoadHandler                // 加载错误事件
    13     , public CefLifeSpanHandler            // 声明周期事件
    14     //, public CefContextMenuHandler    // 上下文菜单事件
    15     //, public CefDialogHandler            // 对话框事件
    16     //, public CefDownloadHandler        // 下载事件
    17     //, public CefDragHandler            // 拖拽事件
    18     //, public CefFindHandler            // 查找事件
    19     //, public ...
    20 {
    21 public:
    22     CCefBrowserEventHandler(CMainFrameWnd* pMainFrame);
    23 
    24     virtual ~CCefBrowserEventHandler();
    25 
    26 public:
    27     // CefClient 事件处理器,如果没有对应处理器则默认使用内部处理器
    28     virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE;
    29     virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE;
    30     virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE;
    31 
    32 public:    
    33     // display handler method
    34     virtual void OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) OVERRIDE;
    35 
    36 public:
    37     // load handler method
    38     virtual void OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, 
    39         ErrorCode errorCode, const CefString& errorText, const CefString& failedUrl) OVERRIDE;
    40 
    41 public:
    42     // display handler meethod
    43     virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
    44     virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
    45     virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
    46 
    47 
    48     virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
    49         CefProcessId source_process,
    50         CefRefPtr<CefProcessMessage> message);
    51 
    52 
    53     bool IsClosing() const { return m_bIsClosing; }
    54 
    55     CefRefPtr<CefBrowser> GetBrowser(){return m_Browser;} 
    56 
    57 protected:
    58 
    59     CefRefPtr<CefBrowser> m_Browser; 
    60 
    61     bool m_bIsClosing;
    62 
    63     CMainFrameWnd*      m_pMainWnd;
    64 
    65     IMPLEMENT_REFCOUNTING(CCefBrowserEventHandler);
    66     //由于CEF采用多线程架构,有必要使用锁和闭包来保证在多不同线程安全的传递数据。IMPLEMENT_LOCKING定义提供了Lock()和Unlock()方法以及AutoLock对象来保证不同代码块同步访问
    67     IMPLEMENT_LOCKING(CCefBrowserEventHandler);//必须包含#include "include/base/cef_lock.h" 
    68 };
    69 
    70 #endif//_CEFBROWSEREVENTHANDLER_H_

    .cpp

      1 #include "CefBrowserEventHandler.h"
      2 #include "stdafx.h"
      3 #include <sstream>
      4 #include <string>
      5 #include "include/cef_app.h"
      6 #include "include/wrapper/cef_closure_task.h"
      7 #include "include/wrapper/cef_helpers.h"
      8 #include "MainFrameWnd.h"
      9 
     10 
     11 CCefBrowserEventHandler::CCefBrowserEventHandler(CMainFrameWnd* pMainFrame)
     12     :m_bIsClosing(false)
     13     ,m_pMainWnd(pMainFrame)
     14 {
     15 
     16 }
     17 
     18 CCefBrowserEventHandler::~CCefBrowserEventHandler()
     19 {
     20 
     21 }
     22 
     23 CefRefPtr<CefDisplayHandler> CCefBrowserEventHandler::GetDisplayHandler()
     24 {
     25     return this;
     26 }
     27 
     28 CefRefPtr<CefLifeSpanHandler> CCefBrowserEventHandler::GetLifeSpanHandler()
     29 {
     30     return this;
     31 }
     32 
     33 CefRefPtr<CefLoadHandler> CCefBrowserEventHandler::GetLoadHandler() 
     34 {
     35     return this;
     36 }
     37 
     38 void CCefBrowserEventHandler::OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) 
     39 {
     40     
     41 }
     42 
     43 void CCefBrowserEventHandler::OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, ErrorCode errorCode, 
     44                                           const CefString& errorText, const CefString& failedUrl) 
     45 {
     46     CEF_REQUIRE_UI_THREAD();
     47     if (ERR_ABORTED == errorCode)
     48         return ;
     49 
     50     std::stringstream ss;
     51     ss <<    "<html><body bgcolor="white">"
     52             "<h2>Failed to load URL " << std::string(failedUrl) <<
     53             " with error " << std::string(errorText) << " (" << errorCode <<
     54             ").</h2></body></html>";
     55     frame->LoadString(ss.str(), failedUrl);
     56 }
     57 
     58 void CCefBrowserEventHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) 
     59 {
     60     CEF_REQUIRE_UI_THREAD();
     61 
     62     //base::AutoLock lock_scope(lock_);
     63 
     64     AutoLock lock_scope(this);
     65 
     66      m_Browser = browser;
     67 
     68 }
     69 
     70 bool CCefBrowserEventHandler::DoClose(CefRefPtr<CefBrowser> browser)
     71 {
     72     CEF_REQUIRE_UI_THREAD();
     73 
     74     //base::AutoLock lock_scope(lock_);
     75     AutoLock lock_scope(this);
     76 
     77 
     78     if(m_Browser) 
     79     {
     80         // Set a flag to indicate that the window close should be allowed.
     81         m_bIsClosing = true;
     82     }
     83 
     84     return false;
     85 }
     86 
     87 void CCefBrowserEventHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) 
     88 {
     89     CEF_REQUIRE_UI_THREAD();
     90 
     91     //base::AutoLock lock_scope(lock_);
     92     AutoLock lock_scope(this);
     93 
     94     if(m_Browser->IsSame(browser))  
     95         m_Browser = NULL;
     96 }
     97 
     98 bool CCefBrowserEventHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
     99                                       CefProcessId source_process,
    100                                       CefRefPtr<CefProcessMessage> message) 
    101 {
    102     const std::string& messageName = message->GetName();
    103     if (messageName == "login_msg") 
    104     {   
    105         // extract message
    106         CefRefPtr<CefListValue> args = message->GetArgumentList();
    107         CefString strUser = args->GetString(0);
    108         CefString strPassword = args->GetString(1);
    109 
    110         m_pMainWnd->CEFLoginJsCallCPP(strUser,strPassword);//窗口类的成员函数
    111 
    112                 //如果函数有返回值也可以通过向Render发送消息传递
    113         //send reply to render process
    114         CefRefPtr<CefProcessMessage> outMsg = CefProcessMessage::Create("login_reply");
    115 
    116         // Retrieve the argument list object.
    117         CefRefPtr<CefListValue> replyArgs = outMsg->GetArgumentList();
    118 
    119         // Populate the argument values.
    120         replyArgs->SetSize(1);
    121         replyArgs->SetInt(0, 0);
    122 
    123         // Send the process message to the renderer process.
    124         browser->SendProcessMessage(PID_RENDERER, outMsg);
    125 
    126         return true;
    127     }
    128 
    129     return false;
    130 }

    Browser进程处理完后向Render进程发了消息,The render process receives the IPC message处理

    .h

     1 #ifndef _CEFBROWSERAPP_H_
     2 #define _CEFBROWSERAPP_H_
     3 #include "include/cef_app.h"
     4 #include "CEFV8HandlerEx.h"
     5 
     6 class CCefBrowserApp
     7     : public CefApp
     8     , public CefBrowserProcessHandler
     9     , public CefRenderProcessHandler
    10 {
    11 public:
    12     CCefBrowserApp();
    13 
    14     virtual ~CCefBrowserApp();
    15 
    16 public:
    17     virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()OVERRIDE { return this; };
    18 
    19 public:
    20     // CefBrowserProcessHandler methods:
    21     virtual void OnContextInitialized();
    22 
    23     //CefRenderProcessHandler methods
    24     virtual void OnWebKitInitialized();
    25 
    26     CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE{ return this; }
    27 
    28     virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context);
    29 
    30     virtual void OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context);
    31 
    32     //收消息
    33     virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message);
    34 
    35 protected:
    36 
    37     CefRefPtr<CCEFV8HandlerEx> m_v8Handler;
    38 
    39     IMPLEMENT_REFCOUNTING(CCefBrowserApp);
    40 };
    41 #endif //_CEFBROWSERAPP_H_

    .cpp

     1 #include "CefBrowserApp.h"
     2 #include "stdafx.h"
     3 
     4 
     5 CCefBrowserApp::CCefBrowserApp()
     6     :m_v8Handler(new CCEFV8HandlerEx)
     7 {
     8 }
     9 
    10 CCefBrowserApp::~CCefBrowserApp()
    11 {
    12 }
    13 
    14 
    15 void CCefBrowserApp::OnContextInitialized()
    16 {
    17     // do nothing here, because we will create browser in my own dialog
    18 }
    19 
    20 void CCefBrowserApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
    21                               CefRefPtr<CefFrame> frame,
    22                               CefRefPtr<CefV8Context> context)
    23 {
    24     // Retrieve the context's window object.
    25     CefRefPtr<CefV8Value> object = context->GetGlobal();
    26 
    27     // Create the "NativeLogin" function.
    28     CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("NativeLogin", m_v8Handler);//第一个参数和SetValue参数保持一致,否则无法调用
    29 
    30     // Add the "NativeLogin" function to the "window" object.
    31     object->SetValue("NativeLogin", func, V8_PROPERTY_ATTRIBUTE_NONE);
    32 
    33     // Add the "register" function to the "window" object.
    34     object->SetValue("register",CefV8Value::CreateFunction("register", m_v8Handler),V8_PROPERTY_ATTRIBUTE_NONE);
    35 }
    36 
    37 void CCefBrowserApp::OnWebKitInitialized()
    38 {
    39     std::string app_code =
    40         "var app;"
    41         "if (!app)"
    42         "    app = {};"
    43         "(function() {"
    44         "    app.GetId = function() {"
    45         "        native function GetId();"
    46         "        return GetId();"
    47         "    };"
    48         "})();";
    49 
    50     // Registered Javascript Function, which will be called by Cpp
    51     "  app.registerJavascriptFunction = function(name,callback) {"
    52         "    native function registerJavascriptFunction();"
    53         "    return registerJavascriptFunction(name,callback);"
    54         "  };"
    55 
    56         "})();";
    57 
    58 
    59     CefRegisterExtension("v8/app", app_code, m_v8Handler);//第一个参数不能为空
    60 }
    61 
    62 void CCefBrowserApp::OnContextReleased(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
    63 {
    64     m_v8Handler = nullptr;
    65 }
    66 
    67 bool CCefBrowserApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,CefProcessId source_process,CefRefPtr<CefProcessMessage> message) 
    68 {
    69     const std::string& messageName = message->GetName();
    70     if (messageName == "login_reply")
    71     {
    72         // extract message
    73         CefRefPtr<CefListValue> args = message->GetArgumentList();
    74         bool status = args->GetBool(0);
    75 
    76         CefRefPtr<CefFrame> frame = browser->GetMainFrame();
    77 
    78         if (status)
    79         {
    80             frame->ExecuteJavaScript("IsSuccess();", frame->GetURL(), 0);
    81         }
    82         
    83         return true;
    84     }
    85 
    86     return false;
    87 }

     

    2.JS CallBack 

     在OnContextCreated()函数中给window绑定函数

    1 // Create the "register" function.
    2     CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("register", m_v8Handler);//第一个参数和SetValue参数保持一致,否则无法调用
    3 
    4 // Add the "register" function to the "window" object.
    5     object->SetValue("register", func, V8_PROPERTY_ATTRIBUTE_NONE);

    在Exectue()函数中处理

    else if (name == "register")
    {
        if (arguments.size() == 1 && arguments[0]->IsFunction()) 
        {
            CefRefPtr<CefV8Value> callback_func_ = arguments[0];
            CefRefPtr<CefV8Context> callback_context_ = CefV8Context::GetCurrentContext();
    
            callback_func_->ExecuteFunction(NULL, arguments);//执行回调函数
    
            return true;
        }
    }

    在HTML的JavaScript里这样写

      function myFunc() 
    {
         // do something in JS.
          alert("callback");
    }
          
    //js CALLback
    function CallBack()
    {
         window.register(myFunc);
    }

     3.C++ 调用 JS

    C++调用JS函数相对简单多了,因为CEF有接口可以直接使用CefFrame::ExecuteJavaScript,看看注释:

     1  ///
     2   // Execute a string of JavaScript code in this frame. The |script_url|
     3   // parameter is the URL where the script in question can be found, if any.
     4   // The renderer may request this URL to show the developer the source of the
     5   // error.  The |start_line| parameter is the base line number to use for error
     6   // reporting.
     7   ///
     8   /*--cef(optional_param=script_url)--*/
     9   virtual void ExecuteJavaScript(const CefString& code,
    10                                  const CefString& script_url,
    11                                  int start_line) =0;

    首先需要获取到我们的浏览器里的主框架对象,code是JS函数和传入参数的字符串,URL可以直接忽略。

    1 CefRefPtr<CefFrame> frame = m_handler->GetBrowser()->GetMainFrame();
    2 
    3 m_handler是我们自己定义的Handler对象
    4 
    5 /C++ 调用js方法
    6 //frame->ExecuteJavaScript(L"Test();",frame->GetURL(),0);//提示框
    7 //frame->ExecuteJavaScript(L"ModifyValue();",frame->GetURL(),0);//无参数函数
    8 frame->ExecuteJavaScript(L"ModifyValue('巴萨牛逼');",frame->GetURL(),0);//有参数函数
    9 如果参数是可变的,可以这样
    CString strJsCode;
    strJsCode.Format(L"setInstallStatus('%s','%s','%d');", lpData->strId.c_str(), strStatus, nPercent);
    其中setInstallStatus是js函数,它有三个参数

    我在HMTL里写的

      function Test()
    {
         alert("js被C++非礼了");
    }
          
     function ModifyValue( arr)
    {
          //document.getElementById("text").innerHTML = "被修改了";
           
        alert(arr);
         document.getElementById("text").innerHTML = arr;
     }
  • 相关阅读:
    [LA7139 Rotation(2014 shanghai onsite)]二维树状数组
    [hdu3068 最长回文]Manacher算法,O(N)求最长回文子串
    《机器学习技法》---GBDT
    《机器学习技法》---支持向量回归
    《机器学习技法》---随机森林
    《机器学习技法》---决策树
    《机器学习技法》---AdaBoost算法
    《机器学习技法》---模型聚合
    ubuntu禁止系统自动升级之界面操作
    python之迭代
  • 原文地址:https://www.cnblogs.com/chechen/p/6138167.html
Copyright © 2011-2022 走看看