miniblink是龙泉寺扫地僧基于chromium内核开发的一款开源浏览器嵌入组件,相对于BlzFans早期开发的WKE组件,在HTML5支持、JS引擎速度、新Web标准兼容性上都有较大改进,而且项目较为活跃,作者还贴心地wke和cef的接口,方便了原有基于WKE项目迁移到miniblink上。近期有幸得到项目主要作者的指点,现将其用于演示功能的WKEXE项目的学习使用笔记记录如下:
与原版WKE演示项目wkeBrowser不同,使用miniblink可以不用在自己的代码中创建程序窗口,而是通过main.cpp中调用的如下函数完成:
void RunApplication(Application* app);
由于不是我们的代码创建窗口,故无法像wkeBrowser一样在RegisterClassEx中指定菜单。要为WKEXE添加菜单栏并响应菜单消息有两种办法:
(1)像wkeBrowser一样,自己创建窗口和菜单,然后把wke相关的消息用wke的接口发过去
(2)动态创建菜单后,通过SetWindowLongPtr函数hook到WKEXE的hwnd的窗口函数处理菜单相关消息
考虑到如果自己创建窗口的话,渲染后的贴图也得自己在WKEXE中实现一遍,所以我就选择了第二种方法:
首先要获得wkexe的进程实例,在main.cpp中添加:
HINSTANCE gHinstance; //用于保存 wkexe 进程实例
在函数WinMain中把hInstance保存到全局变量gHinstance中:
gHinstance = hInstance;
在main.cpp里,添加如下全局变量:
extern HINSTANCE gHinstance; //用于保存 wkexe 进程实例
HWND gHwnd; //用于保存 wkexe 窗口句柄
WNDPROC OldProc; //用于保存 wkexe 窗口原始消息循环回调地址
wkeWebView gWkeWebView; //wkeWebView
在main.cpp的CreateWebWindow里,调用如下代码添加菜单:
HMENU hMenu = LoadMenu(gHinstance, MAKEINTRESOURCE(IDR_MENU1));
gHwnd = wkeGetHostHWND(app->window);
gWkeWebView = app->window;
SetMenu(gHwnd, hMenu);
OldProc = (WNDPROC)SetWindowLongPtr(gHwnd, GWL_WNDPROC, (LONG)NewProc);
同时在main.cpp中添加菜单消息回调代码:
//wkexe新回调函数
LRESULT CALLBACK NewProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case ID_EXIT:
MessageBox(NULL, L"您单击了退出菜单", L"wkexe", MB_OK);
SendMessage(hWnd, WM_CLOSE, NULL, NULL);
break;
default:
break;
}
}
return 0;
//达到过滤消息后,恢复原来在OldProc中保存着的回调函数
default:
return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
}
}
和wke一样,wkexe也可以通过相同的wkeRunJS函数调用JavaScript代码,但不同的是,如果C++代码想要获得JavaScript的返回值,需要在调用的JS代码前加上return:
jsRet = wkeRunJS(gWkeWebView, "return funcforcplusplus(\"\xe4\xbd\xa0\xe5\xa5\xbd ABCDEFG\")");
jsRetStr = jsToStringW(wkeGlobalExec(gWkeWebView), jsRet);
MessageBox(hWnd, jsRetStr, L"runJS返回", 0);
同wke一样,JS调用C++代码也需要绑定,在RunApplication函数中CreateWebWindow之前添加如下代码:
jsBindFunction("msgBox", js_msgBox, 2);//JS调用C++
同时在app.cpp文件中添加:
//JS调用C++
jsValue JS_CALL js_msgBox(jsExecState es)
{
const wchar_t* text = jsToStringW(es, jsArg(es, 0));
const wchar_t* title = jsToStringW(es, jsArg(es, 1));
MessageBox(NULL, text, title, 0);
return jsStringW(es, L"C++返回字符串");
}
这里有个BUG需要注意,miniblink的jsToStringW函数目前只能处理JavaScript传入的字符串参数(作者将在下步更新代码时修正),如果前端msgBox函数传入的参数不是字符串类型,那么会得到空值。
附上前端测试用的HTML代码如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>WKE Test Web Page</title>
<script>
function funcforcplusplus(instr){
document.getElementById('result').value=instr;
return navigator.userAgent;
//return "JavaScript Return 返回啦";
}
</script>
</head>
<body>
<p>WKE Test Web Page</p>
<a href='#' onclick="document.getElementById('result').value=msgBox('TEST Function from JS to Cpp','来自Javascript的调用');">LINK</a>
<textarea rows='6' cols='36' id='result'>hello</textarea>
</body>
</html>