# duiwebview2 **Repository Path**: bruce_code/duiwebview2 ## Basic Information - **Project Name**: duiwebview2 - **Description**: Webview2 的 Duilib插件 - **Primary Language**: C/C++ - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 9 - **Forks**: 3 - **Created**: 2022-11-13 - **Last Updated**: 2025-05-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: webview2, DuiLib ## README # duiwebview2 ### 介绍 WebView2 Duilib 插件\ 本项目实现对 Webview2 封装, 以便能在duilib中调用WebView2的功能\ [Webview2](https://learn.microsoft.com/zh-cn/microsoft-edge/webview2/) 是微软推出的 基于 Chromium 的Web控件。\ 与 CEF 相比的优势:在Win10(包含)之后随系统发布,不需要再随应用一起分发,这样可以有效减少应用安装包的大小,并可随微软官方补丁更新。 ### 项目说明 ``` duiwebview2 插件项目 demo 使用事例 bin\nativeweb 本地测试网页 bin\skin duilib界面资源 webview2.xml 文件中描述了 Webview2 控件支持的属性和事件 inc 控件头文件 ``` ### 环境配置 1. VS2022 2. 使用 NuGet 安装 [Microsoft.Web.WebView2](https://learn.microsoft.com/zh-cn/microsoft-edge/webview2/)。duiwebview2, demo 都需要安装 3. 安装 [vcpkg](https://github.com/microsoft/vcpkg "vcpkg github") ### 初始化插件 ```c++ CPaintManagerUI::LoadPlugin(_T("duiwebview2.dll")); ``` ### 创建控件 在界面描述文件加添加以下节点即可: ```xml ``` ### 网页向Host发送消息 需将 webMessageEnabled 设为 "true" ```javascript function OnTest1(){ let cmd = {'cmd':'hello'} window.chrome.webview.postMessage(JSON.stringify(cmd)); } ``` ### 网页接收Host的消息 需将 webMessageEnabled 设为 "true" ```javascript window.chrome.webview.addEventListener('message', arg => { let eventInfo = JSON.stringify(arg.data); console.log(eventInfo); }); ``` ### Host接收网页消息 在 Notify(TNotifyUI& msg) 的 WebMessageReceived 事件中处理 ```c++ if (msg.sType == _T("WebMessageReceived")) { ICoreWebView2* webview = reinterpret_cast(msg.wParam); ICoreWebView2WebMessageReceivedEventArgs* args = reinterpret_cast(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(); 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向网页发送消息 ```c++ //webview 为 ICoreWebView2 接口指针 webview->PostWebMessageAsJson(LR"({"cmd":"hello-response"})"); ``` ### 设置本地目录的虚拟映射表 如果想访问本地目录的网页,可以设置虚拟映射表 ```c++ auto wv2 = static_cast(msg.pSender); wil::com_ptr webView = wv2->GetWebView2(); //为本地网页目录添加资源映射 wil::com_ptr webView2_3; webView2_3 = webView.try_query(); 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的实现\ 我使用了一种简单的方法,并不标准 ```c++ auto wv2 = static_cast(msg.pSender); wv2->InjectObjectToScript(); ``` ### 网页调用本地对象 ```javascript //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) ``` ### 主要属性 属性|类型|默认值|说明 -----|:-----:|:-----:|---------- homepage|STRING|""|主页 autonavi|BOOL|"true"|创建成功后自动导航 scriptEnable|BOOL|"true"|是否允许执行script defaultScriptDialogs|BOOL|"true"|是否允许默认script对话 webMessageEnabled|BOOL|"true"|是否允许web message builtInErrorPageEnabled|BOOL|"false"|是否允许默认错误页 allowExternalDrop|BOOL|"false"|是否允许拖拽 contextMenusEnabled|BOOL|"false"|是否允许右键菜单 acceleratorKeysEnabled|BOOL|"false"|是否允许快捷键 statusBarEnabled|BOOL|"false"|是否允许状态栏 zoomControlEnabled|BOOL|"false"|是否允许放大缩小 mustHttps|BOOL|"true"|是否必须为https ### 主要事件 事件的参数需要强制类型转换成最终类型 事件|参数|说明 :---:|:---:|--- OnWebView2Created||WebView2创建成功 NavigationStarting|ICoreWebView2* msg.wParam
ICoreWebView2NavigationStartingEventArgs* msg.lParam|开始导航 NavigationCompleted|ICoreWebView2* msg.wParam
ICoreWebView2NavigationCompletedEventArgs* msg.lParam|导航完成 WebMessageReceived|ICoreWebView2* msg.wParam
ICoreWebView2WebMessageReceivedEventArgs* msg.lParam|收到web页发送的消息 FrameNavigationCompleted|ICoreWebView2* msg.wParam
ICoreWebView2NavigationCompletedEventArgs* msg.lParam|iFrame导航完成 ### 关于应用发布 [微软推荐分发模式](https://learn.microsoft.com/zh-cn/microsoft-edge/webview2/concepts/distribution)\ 我是这样做的: 1. 检查注册表确定是否已经安装webview2. 2. 如果没安装,调用Evergreen Bootstrapper引导程序安装webview2. 3. 理论上win10之后(含win10)的系统默认都安装了webview2 ### Demo 效果 ![界面1](https://gitee.com/bruce_code/duiwebview2/raw/master/docimg/demo1.png) ![界面2](https://gitee.com/bruce_code/duiwebview2/raw/master/docimg/demo2.png)