从 Web 端代码调用本机 WinRT 代码

Web 端 JavaScript 代码可以在 wv2winrt 工具 (WebView2 WinRT JS 投影工具) 的帮助下访问本机 WinRT 方法和属性。 wv2winrt 工具为 JavaScript 代码生成所需的代码文件,并启用任何 WinRT API 的方法和属性,包括:

  • WebView2 主机应用的 WinRT API。
  • Windows WinRT API。
  • 第三方 WinRT API。

若要详细了解为何要让 Web 端 JavaScript 代码访问 WinRT 主机应用的方法和属性,请参阅 从 Web 端代码调用本机端代码简介。

为什么 WinRT 和 .NET 使用不同的方法

本文适用于 WinRT WebView2 API,不适用于 .NET WebView2 API。 本文中的 C# 代码将为 .NET WebView2 API 生成(但不运行)。 使用本文的适用于 .NET WebView2 API 的 C# 代码调用 AddHostObjectToScript 将产生错误消息。

投影 WinRT 对象时,需要 wv2winrt 工具 (WebView2 WinRT JS 投影工具) ,因为 WinRT 不支持 IDispatch 或任何其他机制来动态检查和交互 WinRT 对象,WebView2 的 Win32 和 .NET 平台支持这些对象。 有关 的 AddHostObjectToScript.NET 用法,请参阅 从 Web 端代码调用本机端代码 ,而不是本文。

WinUI 3 与 WinUI 2 的设置差异

如果 WinRT WebView2 应用面向 WinUI 3 (Windows 应用 SDK) 而不是 WinUI 2 (UWP) ,下面提供了 WinUI 3 特定步骤的概述:

  • 在非打包应用中,必须执行“使用Windows 运行时组件增强非打包桌面应用”一文中的其他步骤。

  • 将 添加到 WinRTAdapterCsWinRTIncludes

  • 对于 WinUI 3 (Windows 应用 SDK) 应用,main应用项目引用 WinAppSDK,它直接包含其自己的 WebView2 SDK 文件副本,因此不能在不生成错误消息的情况下在main应用项目中包括对 WebView2 SDK 的引用。

  • 项目适配器版本不必匹配。

  • 安装 Visual Studio 2022 Community Edition 的“默认”选项后,在 Visual Studio 安装程序 单击 .NET 卡,然后在右侧选中Windows 应用 SDK C# 模板的复选框。

  • 如果仍未显示正确的项目模板:在Visual Studio 安装程序中,单击 UWP 卡将其选中,选中右侧的 v143 C++ 工具复选框,然后单击“修改”按钮。

此示例的策略和最终目标

策略

本文将指导你完成以下main步骤:

  1. (WebView2 WinRT JS 投影工具) 为 wv2winrt 工具创建 WinRTAdapter 项目。

  2. 对于此示例,请为投影指定以下主机端 API:

  3. 运行 wv2winrt 工具,为所选命名空间或类生成 C++/WinRT 源代码。

  4. 调用 main WinUI 项目中的 AddHostObjectToScript

  5. 从 Web 端 JavaScript 代码 (或从 DevTools 控制台) 调用主机对象的方法和属性。

最终目标

首先,我们将选择一些我们有兴趣从 JavaScript 代码调用的 WinRT API。 对于此示例,我们将对 Windows UWP 应用程序使用命名空间中的 Windows.Globalization WinRT Language 类。 Windows.Globalization.Language 类支持从客户端的本机 OS 获取语言信息。

在 WebView2 主机应用中,Web 端 JavaScript 代码随后可以访问本机端代码中对象的方法和属性 Language

通过 DevTools 控制台访问投影 API

在此示例演练结束时,你将使用 Microsoft Edge DevTools 的 控制台 来测试读取 类的 displayName 主机属性 Language

const Windows = chrome.webview.hostObjects.sync.Windows;
(new Windows.Globalization.Language("en-US")).displayName;

然后,DevTools 控制台将输出 English (United States)或其他语言的显示名称,演示你已从 Web 端 JavaScript 代码调用本机代码:

使用 DevTools 控制台测试从 Web 端代码调用本机代码

同样,可以访问 Windows.System.UserProfile 命名空间 成员。

通过源代码文件访问投影的 API

同样,在源代码文件中,而不是在 DevTools 控制台中,可以访问投影的主机对象。 首先,为脚本运行安装代码:

// early in setup code:
const Windows = chrome.webview.hostObjects.sync.Windows;

然后,在代码的main正文中,添加对投影对象的调用,如下所示:

(new Windows.Globalization.Language("en-US")).displayName;

同样,可以访问 Windows.System.UserProfile 命名空间 成员。

让我们开始吧!

步骤 1:创建或获取基本 WebView2 项目

安装 Visual Studio

  • 如果尚未安装 Visual Studio 2015 或更高版本,请参阅在为 WebView2 设置开发环境中的安装 Visual Studio。 按照该部分中的步骤进行操作,然后返回到此页并继续执行以下步骤。 本文显示了 Visual Studio Community Edition 2022 的屏幕截图。

安装 Microsoft Edge 的预览频道

  • 如果尚未在单独的窗口或选项卡中安装 Microsoft Edge (Beta、Dev 或 Canary) 的预览频道,请参阅为 WebView2 设置开发环境中的安装 Microsoft Edge 预览频道。 按照该部分中的步骤进行操作,然后返回到此页并继续执行以下步骤。

创建或打开基本 WebView2 项目

  1. 执行以下任一方法来获取包含嵌入 WebView2 控件的几行 WebView2 代码的基线初学者项目:

  2. 在本地驱动器上 .sln ,打开上面获取的文件,例如 Samples 存储库解决方案:

    • <your-repos-directory>/WebView2Samples-main/GettingStartedGuides/WinUI2_GettingStarted/MyUWPGetStartApp.sln
    • <your-repos-directory>/WebView2Samples/GettingStartedGuides/WinUI2_GettingStarted/MyUWPGetStartApp.sln

    示例解决方案将在 Visual Studio 中打开:

    为 wv2winrt 工具添加新项目

  3. 在 Visual Studio 中,选择“ 调试>启动调试”。 这会生成项目,然后运行项目的基线版本。 将打开基线应用,例如 MyUWPGetStartApp 窗口:

    WebView2 WinUI 2 UWP 示例窗口

    显示的是一个 WinUI 2 (UWP) 应用,它添加了一个 WebView 控件,设置为最初导航到 Bing.com。 这是通过执行 WinUI 2 中的 WebView2 入门中的步骤 (UWP) 应用而得出的应用。

  4. 关闭应用窗口。

步骤 2:为 wv2winrt 工具添加 WinRTAdapter 项目

接下来, (WebView2 WinRT JS 投影工具) 为 wv2winrt 工具创建 WinRTAdapter 项目。 此项目使用运行工具生成的代码生成库。 此生成的代码允许在 WebView2 控件中公开 WinRT API。

wv2winrt 工具添加项目,如下所示:

  1. 在 Visual Studio 中,打开上一步中的 WinUI 项目。

  2. 在解决方案资源管理器中,右键单击解决方案 (而不是项目) ,然后选择“添加新>项目”。 此时会打开 “添加新项目 ”对话框。

  3. 在“搜索”文本框中,输入 Windows 运行时 组件 (C++/WinRT)

    替代方法:如果不按照下面编号步骤中所述使用 Windows 运行时 组件 (C++/WinRT) 的项目模板添加项目,则需要改为按照 UWP 应用程序 > C++/WinRT 简介中的步骤安装通用 Windows 平台开发工作负载。

  4. 选择Windows 运行时组件 (C++/WinRT) 卡,然后单击“下一步”按钮:

    在“添加新项目”对话框中选择Windows 运行时组件 (C++/WinRT) 卡

    注意: 确保模板名称中包含“C++/WinRT”。 如果未列出此模板,请从Visual Studio 安装程序中安装通用 Windows 平台开发工作负荷。 如果使用 Visual Studio 2019 但仍找不到模板,请从 Visual Studio > 扩展管理扩展安装适用于 VS2019 扩展的 C++/WinRT 模板>和可视化工具

    配置新项目 ”窗口随即打开。

配置和创建项目

  1. 在“ 项目名称 ”文本框中,将项目命名为,特别是 WinRTAdapter注意: 目前,必须使用此特定项目名称。

    在“配置新项目”窗口中,将项目命名为“WinRTAdapter”

    上述屏幕截图中的路径反映了克隆示例存储库的方法。

  2. 单击“创建”按钮。

    此时会打开 “新建 Windows 项目 ”对话框:

    “新建 Windows 项目”对话框

  3. 单击“ 确定” 按钮。

    将创建 WinRTAdapter 项目并将其添加到main项目旁边的解决方案资源管理器中:

    新建的 WinRTAdapter 项目

  4. (Ctrl+Shift+S) 选择“文件>保存所有”。

wv2winrt 工具 (WebView2 WinRT JS 投影工具) 将在此 WinRTAdapter 项目中运行。 在以下步骤中,你将为此项目中的选定类生成代码。

步骤 3:安装适用于 WinRTAdapter 项目的 Windows 实现库

在 WinRTAdapter 项目中, (WIL) 安装 Windows 实现库,如下所示:

  1. 解决方案资源管理器中,右键单击 WinRTAdapter 项目,然后选择“管理 NuGet 包”。 “NuGet 包管理器”窗口将在 Visual Studio 中打开。

  2. “NuGet 包管理器 ”窗口中,单击“ 浏览 ”选项卡。

  3. “NuGet 包管理器”窗口的“搜索”框中,输入“Windows 实现库”,然后选择“Windows 实现库”卡:

    NuGet 包管理器,选择“Windows 实现库”包

  4. 单击“ 安装 ”按钮。 此时会打开 “预览更改 ”对话框:

    WinRTAdapter 项目的 WIL 的“预览更改”对话框

  5. 单击“ 确定” 按钮。

  6. (Ctrl+Shift+S) 选择“文件>保存所有”。

现已为 WinRTAdapter 项目安装 WIL。 Windows 实现库 (WIL) 是一种仅限标头的 C++ 库,可更轻松地使用适用于 Windows 的 COM 编码。 它为 Windows COM 编码模式提供可读、类型安全的 C++ 接口。

步骤 4:为 WinRTAdapter 项目安装 WebView2 预发行版 SDK

在 WinRTAdapter 项目中,还要安装 WebView2 SDK 的预发行版,如下所示:

  1. 在解决方案资源管理器中,右键单击 WinRTAdapter 项目,然后选择“管理 NuGet 包”。 “NuGet 包管理器”窗口随即打开。

  2. “NuGet 包管理器 ”窗口中,单击“ 浏览 ”选项卡。

  3. 选中 “包括预发行版 ”复选框。

  4. “搜索 ”框中,输入 “WebView2”。

  5. 单击 Microsoft.Web.WebView2 卡。 详细信息显示在窗口的中间区域。

  6. “版本” 下拉列表中,选择 WebView2 SDK 的 预发行版 ,或确保选择 “最新预发行版 ”。 版本必须为 1.0.1243.0 或更高版本。 请注意你选择的版本号。

    NuGet 包管理器,选择 WinRTAdapter 项目的 WebView2 SDK 包

  7. 单击“ 安装 ”按钮。 此时会打开 “预览更改 ”对话框:

    用于将 WebView2 SDK 添加到 WinRTAdapter 项目的“预览更改”对话框

  8. 单击“ 确定” 按钮。

  9. (Ctrl+Shift+S) 选择“文件>保存所有”。

现已为 WinRTAdapter 项目安装 WebView2 预发行版 SDK。

步骤 5:仅安装 WebView2 预发布 SDK (WinUI 2)

在 main 项目(如 MyUWPGetStartApp)中,安装与为 WinRTAdapter 项目安装的 WebView2 SDK 的预发行版相同,如下所示:

  1. 在解决方案资源管理器中,右键单击main项目(如 MyUWPGetStartApp),然后选择“管理 NuGet 包”。 “NuGet 包管理器”窗口随即打开。

  2. 选中 “包括预发行版 ”复选框。

  3. 选择“ 浏览 ”选项卡。

  4. “搜索 ”框中,输入 “WebView2”。

  5. 单击 Microsoft.Web.WebView2 卡。 详细信息显示在窗口的中间区域。

  6. “版本” 下拉列表中,选择 WebView2 SDK 的 预发行版 ,或确保选择 “最新预发行版 ”。 请确保使用 WinRTAdapter 项目所用的相同版本;对于面向 WinUI 2 (UWP) 的 WinRT WebView2 应用,这需要与 WinRTAdapter 项目的版本相同。 版本必须为 1.0.1243.0 或更高版本。

  7. 单击“ 安装 ”按钮。 此时会打开“预览更改”对话框,将 WebView2 添加到main项目。

  8. 单击“ 确定” 按钮。

    Visual Studio 看起来应类似于上述步骤部分,只不过现在,NuGet 包管理器已针对main项目而不是 WinRTAdapter 项目打开。

  9. (Ctrl+Shift+S) 选择“文件>保存所有”。

现在为main项目安装了 WebView2 预发布 SDK。

步骤 6:为所选主机 API 生成源代码

接下来, (WebView2 WinRT JS 投影工具) 配置 wv2winrt 工具,以合并要使用的 WinRT 类。 这会生成随后要编译的源文件。 为这些 API 生成代码使 Web 端 JavaScript 代码能够调用这些 API。

在下面的示例步骤中,我们将指定两个 Windows 命名空间, wv2winrt 工具将仅为这些命名空间下的 API 生成源代码:

稍后,当示例应用运行时,你将从 DevTools 控制台调用这些 API,以演示如何从 Web 端代码调用这些指定的主机端 API。

指定命名空间和类,如下所示:

  1. 在解决方案资源管理器中,右键单击 WinRTAdapter 项目,然后选择“属性”。 此时将打开 “WinRTAdapter 属性页 ”对话框。

  2. 在左侧展开并选择“ 常用属性>WebView2”。

  3. “使用 WebView2 WinRT API” 设置为 “否”。 因此,WebView2 SDK 不会将 WebView2 WinRT 组件复制到项目的输出中。 此 WinRTAdapter 项目不调用任何 WebView2 WinRT API,因此它不需要 WinRT 组件。

  4. “使用 wv2winrt 工具 ”设置为 “是”。

  5. “使用 JavaScript 大小写 ”设置为 “是”。

  6. “包括筛选器” 行中,单击右侧的列,单击该单元格中的下拉菜单,然后单击“ 编辑”。 “ 包括筛选器 ”对话框随即打开。

  7. 在最上面的文本框中,将以下字符串粘贴到单独的行上,不带前导空格或尾随空格:

    Windows.System.UserProfile
    Windows.Globalization.Language
    

    “包括筛选器”对话框

    需要指定命名空间或类的完整名称,如上所示。

  8. 单击 “确定” 按钮关闭“ 包括筛选器 ”对话框。

  9. 对于本演练,请确保 WinRTAdapter 属性页 对话框如下所示:

    “WinRTAdapter 属性页”对话框,其中展开了“Common Properties > WebView2”

  10. 单击 “确定” 按钮关闭“ 属性页 ”对话框。

  11. (Ctrl+Shift+S) 选择“文件>保存所有”。

添加指向适配器项目的引用

接下来,在 main 项目中添加指向适配器项目的引用。

在 main 项目(如 MyUWPGetStartApp)中添加指向 WinRTAdapter 项目的引用,如下所示:

  1. 在“解决方案资源管理器”中,展开main项目(如 MyUWPGetStartApp),右键单击“引用”,然后选择“添加引用”。 此时将打开 “引用管理器 ”对话框。

  2. 在左侧的树中,选择“ 项目”。 选中 WinRTAdapter 复选框:

    main项目的“引用管理器”对话框中的“WinRTAdapter”复选框

  3. 单击“ 确定” 按钮关闭“ 引用管理器 ”对话框。

  4. (Ctrl+Shift+S) 选择“文件>保存所有”。

生成 API 代码

接下来,生成 API 代码:

  1. 右键单击 WinRTAdapter 项目,然后选择“ 生成”。

    在 wv2winrt 工具的“包括筛选器”对话框中指定的命名空间或类生成源代码, (WebView2 WinRT JS 投影工具) :

    • Windows.System.UserProfile 命名空间
    • Windows.Globalization.Language
  2. 生成完成后,选择“ 全部文件>保存 ” (Ctrl+Shift+S) 。

重要

如果安装了 WebView2 SDK 的发布版本,但生成失败, error MIDL2011: [msg]unresolved type declaration [context]: Microsoft.Web.WebView2.Core.ICoreWebView2DispatchAdapter [ RuntimeClass 'WinRTAdapter.DispatchAdapter' ]则这是 WebView2 SDK 发布版本中的问题,你需要在上述步骤中将 “使用 WebView2 WinRT API” 更改为 “是 ”。

或者,在项目文件WinRTAdapter.vcxproj的最后一个</ItemGroup>后面添加以下内容:

<ItemGroup Condition="'$(WebView2UseDispatchAdapter)' == 'true'">
 <Reference Include="$(WebView2SDKPath)lib\Microsoft.Web.WebView2.Core.winmd">
   <!-- wv2winrt needs Dispatch Adapter metadata to generate code -->
 </Reference>
</ItemGroup>

将 替换为 $(WebView2SDKPath) 安装 WebView2 SDK 的目录,并将 替换为 \ 末尾的 。 例如:..\<sample-directory>\packages\Microsoft.Web.WebView2.1.0.1264.42\

步骤 7:仅更新目标框架 (WinUI 3)

如果你的应用适用于 WinUI 2 (UWP) ,请跳过此步骤。

步骤 8:在 main 项目中添加主机对象

接下来,将 WinRT 对象从主机应用的本机端传递到主机应用的 Web 端。 为此,请添加调用 InitializeWebView2AsyncAddHostObjectToScript的方法,如下所示:

  1. 在“解决方案资源管理器”中,展开“main”项目(如 MyUWPGetStartApp),展开“MainPage.xaml”,然后选择“MainPage.xaml.cs”。

  2. 在构造函数下 MainPage ,添加以下 InitializeWebView2Async 方法:

    private async void InitializeWebView2Async()
    {
       await WebView2.EnsureCoreWebView2Async();
       var dispatchAdapter = new WinRTAdapter.DispatchAdapter();
       WebView2.CoreWebView2.AddHostObjectToScript("Windows", dispatchAdapter.WrapNamedObject("Windows", dispatchAdapter));
    }
    

    此方法调用 AddHostObjectToScript

    在行 AddHostObjectToScript("Windows", ...中, Windows 是顶级命名空间。 如果具有其他顶级命名空间,则可以添加对 AddHostObjectToScript的其他调用,如以下示例所示:

    WebView2.CoreWebView2.AddHostObjectToScript("RuntimeComponent1", dispatchAdapter.WrapNamedObject("RuntimeComponent1", dispatchAdapter));
    

    调用 WrapNamedObject 将创建命名空间的 RuntimeComponent1 包装器对象。 调用 AddHostObjectToScript 使用名称 RuntimeComponent1将包装的对象添加到脚本中。

    有关如何使用自定义 WinRT 组件的完整指南,请参阅下面的 自定义 (第三方) WinRT 组件

  3. MainPage 构造函数的下面 this.InitializeComponent();,添加以下代码:

    InitializeWebView2Async();
    
  4. 右键单击main项目(如 MyUWPGetStartApp),然后选择“设置为启动项目”。 粗体表示启动项目。

  5. (Ctrl+Shift+S) 选择“文件>保存所有”。

  6. F5 运行示例应用。 启用 WebView2 的 WinUI 2 (UWP) 应用随即打开:

    WebView2 WinUI 2 UWP 应用

主机应用的 Web 端代码 (和 DevTools 控制台) 现在可以调用主机对象的指定命名空间或类的方法和属性。

步骤 9:从 Web 端 JavaScript 调用主机对象上的方法和属性

通过 DevTools 控制台访问投影 API

接下来,使用 DevTools 控制台演示 Web 端代码是否可以调用 在 wv2winrt 工具中指定的主机端 API, (WebView2 WinRT JS 投影工具) :

  1. 如果应用未运行,请在 Visual Studio 中按 F5 运行示例应用。

  2. 单击 WebView2 示例应用窗口的main部分,使其获得焦点,然后按 Ctrl+Shift+I 打开 Microsoft Edge DevTools。 或者,右键单击页面,然后选择“ 检查”。

    此时会打开“Microsoft Edge DevTools”窗口。

  3. 如果未显示 Microsoft Edge DevTools 窗口,请按 Alt+Tab 显示它。

  4. “DevTools” 窗口中,选择“ 控制台 ”选项卡。

  5. 单击“ 清除主机 (清除主机”图标) 按钮,或右键单击 “控制台 ”,然后选择“ 清除主机”。 消息可能会定期显示在控制台中。

  6. 在 DevTools 控制台中,粘贴以下 Windows.Globalization.Language 类 代码,然后按 Enter

    const Windows = chrome.webview.hostObjects.sync.Windows;
    (new Windows.Globalization.Language("en-US")).displayName;
    

    控制台输出语言名称字符串,例如 English (United States),演示可从 Web 端 JavaScript 代码调用应用的主机端 (本机端) 代码:

    使用 DevTools 控制台测试从 Web 端代码调用本机端代码

  7. 请尝试省略括号。 在 DevTools 控制台中,输入以下语句:

    new Windows.Globalization.Language("en-US").displayName;
    

    控制台输出语言名称字符串,例如 English (United States)

    同样,可以访问 Windows.System.UserProfile 命名空间 成员。

  8. 关闭 DevTools 窗口。

  9. 关闭应用。

祝贺你! 你已完成从 JavaScript 代码调用 WinRT 代码的示例演示。

通过源代码文件访问投影的 API

上面,我们使用 DevTools 控制台运行访问投影主机对象的 JavaScript 语句。 同样,可以从源代码文件中访问投影的主机对象。 为此,请先运行脚本的安装代码:

// early in setup code:
const Windows = chrome.webview.hostObjects.sync.Windows;

然后,在代码的main正文中,添加对投影对象的调用,如下所示:

(new Windows.Globalization.Language("en-US")).displayName;

同样,你可以访问 Windows.System.UserProfile API 成员。

本教程步骤已结束。 以下部分是有关 WebView2 WinRT 应用的一般信息。

自定义 (第三方) WinRT 组件

除第一方 OS WinRT API 外, wv2winrt 工具 (WebView2 WinRT JS 投影工具) 还支持自定义第三方 WinRT 组件。

使用 wv2winrt 工具的第三方 WinRT 组件

若要通过 wv2winrt 工具使用自定义 (第三方) WinRT 组件,除了上述步骤外,还执行以下步骤:

  1. 将除 main 应用和 WinRTAdapter 项目以外的第三个项目) (添加到实现 WinRT 类的 Visual Studio 解决方案中。

  2. 将 WinRTAdapter 项目“添加引用”到包含 WinRT 类的新第三个项目。

  3. 更新属性中的 WinRTAdapter 项目的 Include 筛选器,以同时包含新类。

  4. 向 添加一行 InitializeWebView2Async 以添加 winrt 类的命名空间:

    WebView2.CoreWebView2.AddHostObjectToScript("MyCustomNamespace", dispatchAdapter.WrapNamedObject("MyCustomNamespace", dispatchAdapter));

  5. 对于从 Web 调用的简单方法,可以选择将命名空间同步代理添加为脚本中的全局对象。 例如:

    window.MyCustomNamespace = chrome.webview.hostObjects.sync.MyCustomNamespace;

有关此示例,请参阅以下 WebView2 示例:

异步 WinRT 方法

按照上述指南中的步骤操作,应能够使用同步代理。 对于异步方法调用,需要使用 chrome.webview.hostObjects.options.forceAsyncMethodMatches

属性 forceAsyncMethodMatches 是正则表达式的数组,其中,如果任何正则表达式与同步代理上的方法名称匹配,则该方法将改为异步运行。 将其设置为 [/Async$/] 将使其匹配以 后缀 Async结尾的任何方法。 然后,匹配的方法调用的工作方式就像异步代理上的方法一样,并返回可以等待的承诺。

示例:

const Windows = chrome.webview.hostObjects.sync.Windows;
chrome.webview.hostObjects.options.forceAsyncMethodMatches = [/Async$/];

let result = await Windows.System.Launcher.launchUriAsync(new Windows.Foundation.Uri('https://contoso.com/'));

有关详细信息,请参阅 forceAsyncMethodMatchesCoreWebView2.AddHostObjectToScript 方法中的行。

订阅 WinRT 事件

WinRT 事件也通过脚本代理公开。 可以使用 和 removeEventListener(string eventName, function handler) 方法添加和删除实例 WinRT 事件和静态 WinRT 事件的addEventListener(string eventName, function handler)事件处理程序。

这些方法的工作方式与同名的 DOM 方法类似。 使用要订阅的 WinRT 事件的字符串名称作为第一个参数的调用 addEventListener ,以及每当引发事件时要调用的函数回调。 具有相同参数的调用 removeEventListener 取消订阅该事件。 例如:

const Windows = chrome.webview.hostObjects.sync.Windows;
const coreApplication = Windows.ApplicationModel.Core.CoreApplication;
const coreApplicationView = coreApplication.getCurrentView();
const titleBar = coreApplicationView.titleBar;
titleBar.addEventListener('IsVisibleChanged', () => {
    console.log('titlebar visibility changed to: ' + titleBar.isVisible);
});

对于提供事件参数的 WinRT 事件,这些参数作为事件处理程序函数的第一个参数提供。 例如,事件 Windows.Foundation.Collections.PropertySet.MapChanged 具有 IMapChangedEventArgs<string, object> event arg 对象,并且该对象作为回调的参数提供。

const Windows = chrome.webview.hostObjects.sync.Windows;
const propertySet = new Windows.Foundation.Collections.PropertySet();
propertySet.addEventListener('MapChanged', eventArgs => {
    const key = eventArgs.key;
    const collectionChange = eventArgs.collectionChange;
    // ...
});

事件 args 对象还将具有以下属性:

属性名 说明
target 引发事件的 对象
type 事件的字符串名称
detail 提供给 WinRT 委托的所有参数的数组

使 AddHostObjectToScript JavaScript 代理更像其他 JavaScript API

AddHostObjectToScript 默认使用异步和详细代理,但可以使 AddHostObjectToScript JavaScript 代理更像其他 JavaScript API。 若要详细了解 AddHostObjectToScript 及其默认行为,请参阅 AddHostObjectToScript。 此外,如果要从 JavaScript UWP 应用中的 JavaScript WinRT 投影迁移主机应用,或者从基于 EdgeHTML 的 WebView 迁移主机应用,则可能需要使用以下方法,以更好地匹配之前的行为。

若要使 AddHostObjectToScript JavaScript 代理更像其他 JavaScript API,请设置以下属性:

  • chrome.webview.hostObjects.option.defaultSyncProxy - 代理可以是异步的,也可以是同步的。 通常我们知道,在同步代理上调用方法时,结果也应是同步代理。 但在某些情况下,我们将丢失该上下文,例如,在提供对本机代码的函数的引用时,然后本机代码稍后调用该函数。 在这些情况下,除非设置了此属性,否则代理将是异步的。

  • chrome.webview.hostObjects.options.forceAsyncMethodMatches - 这是正则表达式的数组。 如果在同步代理上调用方法,则如果方法名称与此数组中的字符串或正则表达式匹配,则实际上将异步执行方法调用。 将此值设置为 [/Async$/] 将使以 结尾 Async 的任何方法成为异步方法调用。 如果异步方法在此处不匹配并且不强制异步,则将同步调用该方法,从而阻止调用 JavaScript 的执行,然后返回承诺的解析,而不是返回承诺。

  • chrome.webview.hostObjects.options.ignoreMemberNotFoundError - 如果尝试获取代理属性的值,并且该属性在相应的本机类上不存在,则会出现异常 - 除非将此属性设置为 true,在这种情况下,该行为将与 Chakra WinRT 投影行为 (匹配,) 常规 JavaScript 行为,并且返回 undefined 时没有错误。

Chakra WinRT 投影将 WinRT 命名空间直接放在根对象上。 相比之下:

  • AddHostObjectToScript 在 上 chrome.webview.hostObjects放置异步根代理。
  • AddHostObjectToScript 在 上 chrome.webview.hostObjects.sync放置同步根代理。

若要访问 Chakra WinRT 投影代码预期的根代理,可以将根代理 WinRT 命名空间位置分配给根对象。 例如:

window.Windows = chrome.webview.hostObjects.sync.Windows;

若要确保设置所有这些设置的 JavaScript 在任何其他操作之前运行,可以使用 方法将上述语句添加到 JavaScript,也可以指示 WebView2 在运行任何其他脚本 CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync 之前为你注入上述语句。

以下示例演示了上述技术:

webview.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(
            "(() => {" +
                    "if (chrome && chrome.webview) {" +
                        "console.log('Setting up WinRT projection options');" +
                        "chrome.webview.hostObjects.options.defaultSyncProxy = true;" +
                        "chrome.webview.hostObjects.options.forceAsyncMethodMatches = [/Async$/,/AsyncWithSpeller$/];" +
                        "chrome.webview.hostObjects.options.ignoreMemberNotFoundError = true;"  +
                        "window.Windows = chrome.webview.hostObjects.sync.Windows;" +
                    "}" +
                "})();");

获取有关 WebView2 属性的信息

有关 WebView2 属性的信息在两个位置提供:

  • WinRTAdapter 项目的属性页。
  • wv2winrt.exe 命令行帮助。 这是 webView2 WinRT JS 投影工具) (wv2winrt 工具。

WinRTAdapter 项目的属性页

在 WinRTAdapter 项目的属性页中,有关属性的帮助,请单击属性行。 对话框底部会显示帮助:

WinRTAdapter 属性页中列出的属性

有关 wv2winrt.exe 属性的命令行帮助

的命令行帮助 wv2winrt.exe 提供有关 wv2winrt 工具的参数 (WebView2 WinRT JS 投影工具) 的信息。 例如:

参数 说明
verbose 列出一些要标准输出的内容,包括已创建的文件以及有关包含和排除规则的信息。
include 默认情况下,列表将排除命名空间和运行时类,但列出的命名空间和运行时类除外。 include 声明可以是包含该命名空间中所有内容的命名空间,也可以是仅包含该运行时类的运行时类名称。
use-javascript-case 更改生成的代码以生成与 Chakra JavaScript WinRT 投影相同的大小写样式的方法名称、属性名称等。 默认值为生成与 winrt 匹配的名称。
output-path 设置将写入生成的文件的路径。
output-namespace 设置要用于生成的 WinRT 类的命名空间。
winmd-paths 应检查代码生成的所有 winmd 文件的空格分隔列表。

另请参阅

教程和示例:

API 参考:

.NET 等效文章: