C++与JS的交互,相信不用多说,必是精髓。
在写这篇博客之前,我不得不说之前遇到的一个问题:不管怎么搞,都不能回调到C++函数中。原因是什么呢?我没有实例化Cefapp。不实例化cefapp也能加载出页面,正常的进行显示,但是在js代码中写回调,回调不到C++中!为什么会犯这么低级的错误呢?实际上,在刚刚接触CEF代码时,真的是一头雾水,在网上各种抄代码,抄的最后“四不像”。以至于,自己的代码都是东拼西凑出来的,里面的逻辑一团糟。到研究到交互时,完了,怎么搞都回调不上来,什么settings.single_process = true啊,统统不好使。(不过这个是将来断点调试的关键代码!大家必须写上!)
下面,我来给大家写一下该怎么进行回调。
一、首先clientapp类应该继承CefRenderProcessHandler类,然后重写virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,CefRefPtr<CefV8Context> context) OVERRIDE;这个函数。这个函数就是用来绑定js的回调函数的。
二、其次写一个重载CefV8Handler的子类,重写virtual bool Execute(
const CefString& name /*JavaScript调用的C++方法名字*/,
CefRefPtr<CefV8Value> object /*JavaScript调用者对象*/,
const CefV8ValueList& arguments /*JavaScript传递的参数*/,
CefRefPtr<CefV8Value>& retval /*返回给JS的值设置给这个对*/,
CefString& exception/*通知异常信息给JavaScript*/);函数,将来js的函数会回调到这里。
三、在html代码中假如window打头的回调函数代码。
接下来,我给大家举个例子。
在OnContextCreated函数中添加如下代码:
CefRefPtr<CefV8Value> window = context->GetGlobal();// 获取到window
// 添加js创建函数
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("NativeLogin", m_v8Handler);//new ClientAppExtensionHandler(this));
window->SetValue("NativeLogin", func, V8_PROPERTY_ATTRIBUTE_NONE);
Execute中添加如下代码
if (name == "NativeLogin")
{
if (arguments.size() == 2)
{
CefString strUser = arguments.at(0)->GetStringValue();
CefString strPassword = arguments.at(1)->GetStringValue();
TCHAR szLog[256] = { 0 };
_stprintf_s(szLog, 256, _T("user - %s, password - %s\r\n"), strUser.c_str(), strPassword.c_str());
OutputDebugString(szLog);
}
return true;
}
网页中代码可以这么写
function Login(){
//alert(window.NativeLogin(document.getElementById("userName").value, document.getElementById("password").value));
window.NativeLogin(document.getElementById("userName").value, document.getElementById("password").value);
}
<form>
UserName: <input type="text" id="userName" /> Password:
<input type="text" id="password" /> <input type="button" value="Login" onclick="Login()"/></form>
这样点击网页上Login按钮时,在Execute函数中打断点,就会进到函数体内。这样一个简单的js回调就完成了。
如果想要扩展其灵活性,就需要读者对其下功夫了,举一反三触类旁通嘛!