1. 程式人生 > 其它 >icpc 46 上海站 g題

icpc 46 上海站 g題

本文將介紹如何在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
  • 選擇預設版本並點 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
  • 在 Toolbox 點 Common 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的導航事件

    當一個錯誤發生時,會引發以下事件,可能取決於對錯誤網頁的導航
  • 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 的網站時顯示警報

9. 宿主程式與頁面之間的通訊

宿主程式和頁面內容可以使用 postMessage 進行通訊如下:

  • WebView2 控制元件中的 Web 內容可以使用 window.chrome.webview.postMessage 向宿主程式釋出訊息。宿主程式使用任何註冊到 WebMessageReceived 委託方法處理訊息。
  • 主程式使用 CoreWebView2.PostWebMessageAsString 或 CoreWebView2.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 應用就完成了。

本文將介紹如何在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
  • 選擇預設版本並點 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
  • 在 Toolbox 點 Common 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的導航事件

    當一個錯誤發生時,會引發以下事件,可能取決於對錯誤網頁的導航
  • 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 的網站時顯示警報

9. 宿主程式與頁面之間的通訊

宿主程式和頁面內容可以使用 postMessage 進行通訊如下:

  • WebView2 控制元件中的 Web 內容可以使用 window.chrome.webview.postMessage 向宿主程式釋出訊息。宿主程式使用任何註冊到 WebMessageReceived 委託方法處理訊息。
  • 主程式使用 CoreWebView2.PostWebMessageAsString 或 CoreWebView2.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 應用就完成了。