本文中使用的是Cef加载网页,实现网页中javascript和mfc代码之间相互调用,即是mfc调用javascript,javascript调用mfc代码。
一、javascript调用mfc代码
①搭建mfc加载cef的框架,并加载网页,这部分内容在网上有很多博文,不过会遇到一些崩溃,或者无法正常退出,或者多进程和单进程问题,或者加载网页慢等问题,在我其他博文中有一部分解决方案介绍,这里跳过这部分。
②首先是在SimpleApp类中重写虚函数OnContextCreated,这部分相当于是订阅javascript调用信息,回调信息在CefV8Handler中实现,头文件定义如下:
virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) OVERRIDE;
在具体实现中代码如下:
// The var type can accept all object or variable
CefRefPtr<CefV8Value> pV8 = context->GetGlobal();
// bind function
CefRefPtr<CSimpleV8Handler> pJsHandler(new CSimpleV8Handler());
CefRefPtr<CefV8Value> pFunc = CefV8Value::CreateFunction(CefString("JSCallCppCB"), pJsHandler);
pV8->SetValue(CefString("JSCallCppCB"), pFunc, V8_PROPERTY_ATTRIBUTE_NONE);
这里的字符串“JSCallCppCB"是需要记住的,这个名字可以修改,但是要保持这个名字和javascript上调用的名字一样,不然是不能调用成功的,后面介绍javascript上怎么写。
③在cef的CefV8Handler的继承类CSimpleV8Handler中重写虚函数Execute,这部分相当于实现cef的回调处理。头文件定义入下:
virtual bool Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments,CefRefPtr<CefV8Value>& retval, CefString& exception) OVERRIDE;
在具体实现中的代码如下:
bool CSimpleV8Handler::Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments,CefRefPtr<CefV8Value>& retval, CefString& exception)
{
if (name == CefString("JSCallCppCB")){ //这里根据回调名字区分
if (arguments.size() ==2 ){ //判断网页上传递的形参个数
CefString str = arguments[0]->GetStringValue(); //获取第一个形参的值
int value = arguments[1]->GetIntValue(); //获取第二个形参的值
//做一些其他事情
return true;
}
}
return false;
}
在这里遇到一个神奇的问题,就是打断点无论如何都停不下来,开始我以为代码根本没执行,但是弹出一个信息提示框发现是有提示框的,但就是断点不起作用,在另一篇文章里面有详细说明,另外在文末的连接中有一个完整的代码。
④最关注的就是网页上如何调用这个方法了,下面试javascript调用代码,很简单:
var str = document.getElementById('cefInput').value;
window.JSCallCppCB(str,1);
注意这里的函数名和cef中的订阅名字是一样的,和回调中的名字也是一样的,直到这里就可以完美的从javascript中调用mfc代码了,参数可以传递多个。
二、mfc调用javascript代码
①mfc代码
这部分有点点不一样了,网上有直接在v8引擎中调用的,不过这个调用代码写在哪儿看需求,我是直接写在浏览器的Dlg中的,实现如下:
if (m_simpleClient.get()){
CefRefPtr<CefBrowser>browser = m_simpleClient->GetBrowser(m_hWnd);
if (browser){
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
CString jscall = _T("ChangeText('");
jscall += str;
jscall += _T("');");
frame->ExecuteJavaScript(jscall.GetBuffer(), frame->GetURL(), 0);
}
}
其中m_simpleClient是cef浏览器句柄,这个是在创建浏览器的时候的一个类变量,如果不清楚怎么创建cef浏览器,请网上查阅。
②javascript代码
function ChangeText(v){
//做一些事情
}
这里也可以传递多个参数,只需要在c++代码中组装好调用的字符串,javascript中写好定义即可,注意参数一致。
本文涌动的例子可以在下面的地址下载,这是一个基于VS2013的mfc上显示cef浏览器和ie插件浏览器,实现cef的JavaScript和ie的JavaScript相互调用的示例代码,下载地址为:https://download.csdn.net/download/youyicc/12113708