.NET桌面程序混合开发之二:在原生WinFrom程序中使用WebView2

.NET桌面程序混合开发之二:在原生WinFrom程序中使用WebView2

本文将介绍如何在WinForms中嵌入WebView2,并讲到WebView2的主要特征。点击了解更多WebView2的API

1. 准备

  • Visual Studio 2017 及以上版本
  • WebView2运行时,或者安装Beta,Dev,Canary任一版本的 Microsoft Edge 预览版。受支持的操作系统有:Windows 11\10\8.1\7
  • 推荐使用82.0.488.0以上的Canary(日更)版本。

2. 创建单窗体应用

创那一个只包括主窗体的桌面项目:

  • 打开Visual Studio
  • 依次点 文件->新建->工程
  • 创建新的工程
    创建新工程
  • 选择 C# Windows Forms App (.NET Framework) ,然后点 Next
    工程类型
  • 输入 工程名称位置 ,在 Framework下拉列表中,选择 ** .NET Framework 4.7.2** 或以上版本
    工程设置
  • 创建

3. 安装 WebView2 SDK

使用 NuGet 为工程添加 WebView2 SDK

  • Solution Explorer 右键点击工程名,在弹出菜单中选择 Manage NuGet Packages
  • 管理包
  • Browse
  • 选择 Include prerelease(包含预览版)
  • 在查找框中,输入WebView2,在结果中选择 Microsoft.Web.WebView2
  • 查找WebView2
  • 选择默认版本并点 Install
    选择默认版本
  • Ok
  • File > Save All (Ctrl+Shift+S) ,保存工程
  • F5 编译并运行后,程序的运行结果是一个空窗体
    运行结果

4. 创建一个WebView

在你的应用中添加一个WebView2控件。

  • Project > Add Form (Windows Forms)
  • Add New Item 窗口中,依次点 Visual C# Items > Web > Windows Forms > Form (Windows Forms) ,然后点 Add
  • View > Toolbox
  • Toolbox ,点开 WebView2 Windows Forms Control
注意:如果你用的是Visual Studio 2017,在Toolbox中默认是找不到WebView2控件的。若想让其显示,则需要依次选 Tools > Options > General 并且将 Automatically Populate Toolbox 设置为 true
  • WebView2 控件拖到 Form 窗体上。
    添加到窗体
  • Properties 工具框中,将 Name 属性设置为 webView。可以使用 分类- 按字母排序 来找到需要的属性
    属性查找
  • WebView2的 Source 属性用于初始化页面的URI。将其值设置为:https://www.microsoft.com
  • File > Save All (Ctrl+Shift+S) 保存工程
  • F5 编译运行工程
  • WebView2 控件中显示如下:
    编译运行

注意:如果你的是高分辨率显示器,你需要为窗体应用设置置高分辨率支持

5. 添加控件及处理窗体resize事件

从Toolbox中添加更多控件,并处理窗体的resize事件。

  • View > Toolbox
  • ToolboxCommon Controls
  • TextBox 拖动到窗体上
  • Properties属性设置窗口,将Name 属性设置为 addressBar
  • Toolbox 中拖动 Button 控件到窗体上
  • Properties属性设置窗口,将Name 属性设置为 goButton
  • Text属性设置为 Go!
  • 调整Button大小以适应文字
  • 将文本框放在Button左侧,并与按钮文字对齐如下
    对齐
  • 重置窗体大小
    重置窗体大小
  • View > Code 打开窗体代码文件。编写 Form_Resize函数处理窗体大小改变时,控件在恰当的位置。
  • 删除如下代码
public Form1()
{
    InitializeComponent();
}
  • 拷贝如下代码到刚删除的代码的相同位置
public Form1()
{
    InitializeComponent();
    this.Resize += new System.EventHandler(this.Form_Resize);
}

private void Form_Resize(object sender, EventArgs e)
{
    webView.Size = this.ClientSize - new System.Drawing.Size(webView.Location);
    goButton.Left = this.ClientSize.Width - goButton.Width;
    addressBar.Width = goButton.Left - addressBar.Left;
}
  • 点**File > Save All (Ctrl+Shift+S) **保存工程
  • F5编译运行,效果如下:
    运行效果

6. 地址导航

在应用中添加地址栏,让用户可以通过改变地址栏来改变WebView2展示的内容。

  • Form1.cs中添加CoreWebView2命名空间,代码如下:
using Microsoft.Web.WebView2.Core;
  • 在窗体设计界面,双击Go按钮,以在Form1.cs中添加 goButton_Click事件响应方法,将以下代码拷到方法中:
private void goButton_Click(object sender, EventArgs e)
{
    if (webView != null && webView.CoreWebView2 != null)
    {
        webView.CoreWebView2.Navigate(addressBar.Text);
    }
}
这样,```goButton_Click```方法就实现了当用户在地址栏输入地址并点击Go按钮时,WebView2就将显示址址栏中的地址所代表的页面内容。
  • 点 **File > Save All (Ctrl+Shift+S) **保存工程
  • F5编译并运行
  • 在地址栏中输入你想访问的地址关点Go,验证下窗口上显示的是不是你想要的内容吧。
    注意:在地址栏中应输入完整的URL,如果址址不是以 http://https:// 开头的话,会遇到ArgumentException 异常

在页面跳转过程中,WebView2控件会发起一系列事件。而嵌入WebView2的应用会监听到以下事件:

  • NavigationStarting
  • SourceChanged
  • ContentLoading
  • HistoryChanged
  • NavigationCompleted
    了解更多关于WebView2的导航事件
    events of WebView2
    当一个错误发生时,会引发以下事件,可能取决于对错误网页的导航
  • SourceChanged
  • ContentLoading
  • HistoryChanged
    以下操作,将为NavigationStarting委托注册一个处理方法,处理当地址不是Https时,取消页面请求。通过此例来展示如何使用这些事件。
  • Form1.cs 中,做如下代码更改,添加一个EnsureHttps方法
public Form1()
{
    InitializeComponent();
    this.Resize += new System.EventHandler(this.Form_Resize);

    webView.NavigationStarting += EnsureHttps;
}

void EnsureHttps(object sender, CoreWebView2NavigationStartingEventArgs args)
{
    String uri = args.Uri;
    if (!uri.StartsWith("https://"))
    {
        args.Cancel = true;
    }
}

在构造函数中,EnsureHttps被注册为WebView2控件的NavigationStarting 的事件处理方法。

  • File > Save All (Ctrl+Shift+S) 保存工程
  • F5 编译运行
  • 如果访问HTTPS会打开正常的页面,如果是HTTP则不会正常访问

8. 脚本

主程序可以在运行时向WebView2注入JavaScript脚本。可以让WebView2运行任意的JavaScript,或者添加初始化脚本。注入的JavaScript适用于所有新的顶层文档和任何子框架,直到JavaScript被删除。注入的 JavaScript 以特定的时间运行。

  • 在创建全局对象后运行注入的JavaScript。
  • 在运行HTML文档中包含的任何其他脚本之前运行注入的JavaScript。

1.例如,在用户导航到非 HTTPS 站点时,添加发送警报的脚本。修改EnsureHttps函数,使用ExecuteScriptAsync方法将脚本注入到网页内容中,如下图所示

void EnsureHttps(object sender, CoreWebView2NavigationStartingEventArgs args)
{
    String uri = args.Uri;
    if (!uri.StartsWith("https://"))
    {
        webView.CoreWebView2.ExecuteScriptAsync($"alert('{uri} is not safe, try an https link')");
        args.Cancel = true;
    }
}
  1. File > Save All (Ctrl+Shift+S) 保存工程
  2. F5 编译运行
  3. 应用在访问非 HTTPS 的网站时显示警报
    alert

9. 宿主程序与页面之间的通讯

宿主程序和页面内容可以使用 postMessage 进行通信如下:

  • WebView2 控件中的 Web 内容可以使用 window.chrome.webview.postMessage 向宿主程序发布消息。宿主程序使用任何注册到 WebMessageReceived 委托方法处理消息。
  • 主程序使用 CoreWebView2.PostWebMessageAsStringCoreWebView2.PostWebMessageAsJSON 将消息发布到 WebView2 控件中的 Web 内容。这些消息由添加到 window.chrome.webview.addEventListener 的处理程序捕获。

通信机制使用原生功能将消息从 Web 内容传递到宿主程序。
在项目中,当 WebView2 控件(通过页面链接)导航到一个页面时,它会在地址栏中显示新网页的 URL 并弹出新网页的 URL。

  1. Form1.cs 文件中,更新构造函数并创建 InitializeAsync 函数,代码片段如下:
public Form1()
{
   InitializeComponent();
   this.Resize += new System.EventHandler(this.Form_Resize);
   webView.NavigationStarting += EnsureHttps;
   InitializeAsync();
}

async void InitializeAsync()
{
   await webView.EnsureCoreWebView2Async(null);
}

InitializeAsync 函数里,要用EnsureCoreWebView2Async awaits 调用方式,因为CoreWebView2 的初始化是异步的。

  1. CoreWebView2 初始化后,注册一个事件处理方法来响应 WebMessageReceived 事件。在 Form1.cs 文件中,使用以下代码替换 InitializeAsync 并添加 UpdateAddressBar
async void InitializeAsync()
{
    await webView.EnsureCoreWebView2Async(null);
    webView.CoreWebView2.WebMessageReceived += UpdateAddressBar;
}

void UpdateAddressBar(object sender, CoreWebView2WebMessageReceivedEventArgs args)
{
    String uri = args.TryGetWebMessageAsString();
    addressBar.Text = uri;
    webView.CoreWebView2.PostWebMessageAsString(uri);
}
  1. 为了让WebView2发送和响应web消息,CoreWebView2初始化后,宿主程序在web内容中注入一个脚本:
    a. 使用 postMessage 将 URL 发送到宿主程序。
    b. 注册一个事件处理程序以打印从宿主程序发送的消息。

  2. Form1.cs 文件中,用以下代码段修改 InitializeAsync

async void InitializeAsync()
{
    await webView.EnsureCoreWebView2Async(null);
    webView.CoreWebView2.WebMessageReceived += UpdateAddressBar;

    await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.postMessage(window.document.URL);");
    await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.addEventListener(\'message\', event => alert(event.data));");
}
  1. File > Save All (Ctrl+Shift+S) 保存工程
  2. F5 编译运行
  3. 当通过页面链接访问到新的URI时,WebView2 控件便会将新页面地址显示到地址栏。
    至此,一个 WebView2 应用就完成了。
posted @ 2022-01-02 17:10  sammy621  阅读(4148)  评论(1编辑  收藏  举报