WinFormsでChromium版Edgeブラウザコンポーネント(WebView2)を使ってみる

# はじめに
これは、[Visual Basic Advent Calendar 2021](https://qiita.com/advent-calendar/2021/vb)の21日目の記事となります。

Visual Basicのネタとして、WebView2 コントロールを使用したものを作成しておきたい。
以前、CefSharpを使用した記事を書いた。この記事をベースに WebView2 コントロール用に書き換える。

https://qiita.com/yaju/items/6fc1b72e60dbcc031669
 
>データをセットしてボタンをクリックして結果を得られるようなサイトが何かないかなーと思っていたら、以前に行列計算で活用したサイトがありました。
体脂肪率なら身長と体重を入力させて体脂肪率の結果を得られることが分かったので、これをサンプルとして活用していきます。
[Keisan 生活や実務に役立つ計算サイト - 体脂肪率](https://keisan.casio.jp/exec/system/1161228728)

# 開発環境
* Windows 11 Home
* Visual Studio Community 2022（Visual Basic）
* WinForm(.NET6.0)
* WebView2コントロール 1.0.1054.31

## 準備
新規プロジェクトにて、WindowsForm(.NET6.0)を言語をVisual Basicでプロジェクト名「WebViewApp」で作成します。

NuGetパケットマネージャで「Microsoft Web WebView2」をインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/5093a89a-8d8b-8019-5f43-7b0218ac3249.png)

ツールボックスからMenuStripをフォームにドラッグ＆ドロップします。
次にツールボックスからWebView2をフォームにドラッグ＆ドロップして貼り付けます。WebView2のAnchorプロパティにてTop,Left,Right,Buttomをクリックしてフォームのリサイズで自動的にWebView2のサイズが変わるようにしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/1d5ce50e-1147-8d4a-2982-45bf65f64a88.png)

# WebView2操作
## URLの取得
現在表示しているURLを取得します。

```vb
Me.WebView21.Source.ToString()
```

## URLの変更
起動時は、Googleサイトを表示します。

```vb
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Me.WebView21.Source = New Uri("https://www.google.com")
End Sub
```

メニュー(MenuStrip)にBMI項目を作成してBMIメニューをクリックしたら、体脂肪率サイトを表示するようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/1dd0b148-bf45-0901-5cbd-e83bff2cc66a.png)

```vb
Private Sub BMIToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BMIToolStripMenuItem.Click
    Me.WebView21.Source = New Uri("https://keisan.casio.jp/exec/system/1161228728")
End Sub
```

## ブラウザ読込完了時イベント
WebView(IE)の読み込み完了イベントの`DocumentCompleted`は、WebView2では`NavigationCompleted`に置き換わります。
IsSuccess が True になった時に読込完了処理を記述します。

```vb
Private Async Sub WebView21_NavigationCompleted(sender As Object, e As Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs) Handles WebView21.NavigationCompleted
    If e.IsSuccess Then
```

## HTML要素の値セットとボタンクリック
HTML要素の値のセットやクリックは、`ExecuteScriptAsync`メソッドに Javascript のスクリプトをセットして実現します。

身長のテキストのIdは"var_身長"、体重のテキストのIdは"var_体重"、計算ボタンのIdは"executebtn"となります。
身長と体重をセットしたら、ボタンをクリックします。

```vb
jsScript = String.Format("document.getElementById('var_身長').value = '{0}';", 180)
jsScript &= String.Format("document.getElementById('var_体重').value = '{0}';", 54)
jsScript &= "document.getElementById('executebtn').click();"
Await Me.WebView21.ExecuteScriptAsync(jsScript)
```

## HTML要素の値の取得
HTML要素の値の取得には `ExecuteScriptAsync`メソッドに Javascript のスクリプトをセットして実現します。
体脂肪率のDIVタグのIdは"ans1"となります。

サイトが更新されて体脂肪率の結果が得られたら、画面にメッセージボックスで体脂肪率を表示しています。

```vb
jsScript = "document.getElementById('ans1').innerText;"
_anser = Await WebView21.ExecuteScriptAsync(jsScript)
_anser = _anser.Replace("""", "").Trim()
MessageBox.Show("BMI = " & Double.Parse(_anser))
```

## 最終結果
```vb
Public Class Form1
    Private _anser As String = ""
    Private _isSetValue As Boolean = False

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.WebView21.Source = New Uri("https://www.google.com")
    End Sub

    Private Async Sub WebView21_NavigationCompleted(sender As Object, e As Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs) Handles WebView21.NavigationCompleted
        If e.IsSuccess Then
            ' 読込完了処理を記述
            Dim jsScript As String
            If Me.WebView21.Source.ToString().IndexOf("keisan") >= 0 And _anser.Trim = "" Then
                If Not _isSetValue Then
                    jsScript = String.Format("document.getElementById('var_身長').value = '{0}';", 180)
                    jsScript &= String.Format("document.getElementById('var_体重').value = '{0}';", 54)
                    jsScript &= "document.getElementById('executebtn').click();"
                    Await Me.WebView21.ExecuteScriptAsync(jsScript)
                    _isSetValue = True
                Else
                    jsScript = "document.getElementById('ans1').innerText;"
                    _anser = Await WebView21.ExecuteScriptAsync(jsScript)
                    _anser = _anser.Replace("""", "").Trim()
                    MessageBox.Show("BMI = " & Double.Parse(_anser))
                    _anser = ""
                    _isSetValue = False
                End If
            End If
        End If
    End Sub

    Private Sub BMIToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BMIToolStripMenuItem.Click
        Me.WebView21.Source = New Uri("https://keisan.casio.jp/exec/system/1161228728")
    End Sub
End Class
```

### 起動時
Googleサイトが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/216a27d2-0ba6-8cef-7ada-3f7d3646c75c.png)

### BMIメニューをクリック
体脂肪率サイトが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/76ee21ae-128b-b86c-a34c-8ad92d33535a.png)

# 最後に
CefSharpも悪くないですが、Windowsで標準で用意されている WebView2 コントロールが使えるなら他のフォームコントロール同様にドラッグ＆ドロップで貼り付け出来るし、プロパティも見れるし作りやすそうです。

# 参照
* [プログラムでネットサーフィン！ WebView2コントロールでの操作](https://web.biz-prog.net/readme/webview_new2.html)
* [WebView2 - SYSART-MAGAZIN システム開発備忘録](https://sysart-magazin.com/category/%e3%82%b7%e3%82%b9%e3%83%86%e3%83%a0%e9%96%8b%e7%99%ba%e5%82%99%e5%bf%98%e9%8c%b2/webview2/)