Duilib的WebView2开源插件

duiwebview2

项目地址

gitee地址 

介绍

WebView2 Duilib 插件
本项目实现对 Webview2 封装, 以便能在duilib中调用WebView2的功能
Webview2  是微软推出的 基于 Chromium 的Web控件。
与 CEF 相比的优势:在Win10(包含)之后随系统发布,不需要再随应用一起分发,这样可以有效减少应用安装包的大小,并可随微软官方补丁更新。

项目说明

duiwebview2     插件项目
demo            使用事例
bin\nativeweb   本地测试网页
bin\skin        duilib界面资源
webview2.xml    文件中描述了 Webview2 控件支持的属性和事件
inc             控件头文件

环境配置

  1. VS2022
  2. 使用 NuGet 安装  Microsoft.Web.WebView2  。duiwebview2, demo 都需要安装
  3. 安装  vcpkg 

初始化插件

CPaintManagerUI::LoadPlugin(_T("duiwebview2.dll"));

创建控件

在界面描述文件加添加以下节点即可:

<Webview2 name="mainview" homepage="https://baidu.com" bkcolor="0xFFFFFFFF"/>

网页向Host发送消息

需将 webMessageEnabled 设为 "true"

function OnTest1(){
    let cmd = {'cmd':'hello'}
    window.chrome.webview.postMessage(JSON.stringify(cmd));
}

网页接收Host的消息

需将 webMessageEnabled 设为 "true"

window.chrome.webview.addEventListener('message', arg => {
    let eventInfo = JSON.stringify(arg.data);
    console.log(eventInfo);
});

Host接收网页消息

在 Notify(TNotifyUI& msg) 的 WebMessageReceived 事件中处理

if (msg.sType == _T("WebMessageReceived")) {
    ICoreWebView2* webview = reinterpret_cast<ICoreWebView2*>(msg.wParam);
    ICoreWebView2WebMessageReceivedEventArgs* args = reinterpret_cast<ICoreWebView2WebMessageReceivedEventArgs*>(msg.lParam);
    wil::unique_cotaskmem_string message;
    CHECK_FAILURE(args->TryGetWebMessageAsString(&message));
    //将unicode转为utf8
    auto msg = g_conv.to_bytes(message.get());
    try {
        auto cmdObj = json::parse(msg);
        auto cmd = cmdObj["cmd"].get<std::string>();
        if (cmd.compare("hello") == 0){
            webview->PostWebMessageAsJson(LR"({"cmd":"hello-response"})");
        }
        else if (cmd.compare("runscript") == 0) {
            m_pWebTest->ExecuteScript(LR"(scriptFunction(5,11);)", NULL);
        }
    }
    catch (std::exception& e) {
        ATLTRACE("%s\n", e.what());
    }
}

Host向网页发送消息

//webview 为 ICoreWebView2 接口指针
webview->PostWebMessageAsJson(LR"({"cmd":"hello-response"})");

设置本地目录的虚拟映射表

如果想访问本地目录的网页,可以设置虚拟映射表

auto wv2 = static_cast<DuiLib::CWebview2UI*>(msg.pSender);
wil::com_ptr<ICoreWebView2> webView = wv2->GetWebView2();
//为本地网页目录添加资源映射
wil::com_ptr<ICoreWebView2_3> webView2_3;
webView2_3 = webView.try_query<ICoreWebView2_3>();
if (webView2_3)
{
    //这样就可以用 https://native.test/test.html 访问本地网页了
    webView2_3->SetVirtualHostNameToFolderMapping(
        L"native.test", L"..\\..\\nativeweb",
        COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS);
}

注入本地对象供javascript调用

NativeObj为c++实现的双接口本地对象,具体可查看Demo的实现
我使用了一种简单的方法,并不标准

auto wv2 = static_cast<DuiLib::CWebview2UI*>(msg.pSender);
wv2->InjectObjectToScript<NativeObj>();

网页调用本地对象

//NativeObj为本地对象

//调用Add方法
chrome.webview.hostObjects.sync.NativeObj.Add(1,2);

//调用info属性
chrome.webview.hostObjects.sync.NativeObj.info = '哈哈哈';
window.alert(chrome.webview.hostObjects.sync.NativeObj.info)

主要属性

属性类型默认值说明
homepageSTRING""主页
autonaviBOOL"true"创建成功后自动导航
scriptEnableBOOL"true"是否允许执行script
defaultScriptDialogsBOOL"true"是否允许默认script对话
webMessageEnabledBOOL"true"是否允许web message
builtInErrorPageEnabledBOOL"false"是否允许默认错误页
allowExternalDropBOOL"false"是否允许拖拽
contextMenusEnabledBOOL"false"是否允许右键菜单
acceleratorKeysEnabledBOOL"false"是否允许快捷键
statusBarEnabledBOOL"false"是否允许状态栏
zoomControlEnabledBOOL"false"是否允许放大缩小
mustHttpsBOOL"true"是否必须为https

主要事件

事件的参数需要强制类型转换成最终类型

事件参数说明
OnWebView2CreatedWebView2创建成功
NavigationStartingICoreWebView2* msg.wParam <br/>ICoreWebView2NavigationStartingEventArgs* msg.lParam开始导航
NavigationCompletedICoreWebView2* msg.wParam<br/>ICoreWebView2NavigationCompletedEventArgs* msg.lParam导航完成
WebMessageReceivedICoreWebView2* msg.wParam<br/>ICoreWebView2WebMessageReceivedEventArgs* msg.lParam收到web页发送的消息
FrameNavigationCompletedICoreWebView2* msg.wParam<br/>ICoreWebView2NavigationCompletedEventArgs* msg.lParamiFrame导航完成

关于应用发布

微软推荐分发模式 
我是这样做的:

  1. 检查注册表确定是否已经安装webview2.
  2. 如果没安装,调用Evergreen Bootstrapper引导程序安装webview2.
  3. 理论上win10之后(含win10)的系统默认都安装了webview2

Demo 效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值