WinFormsでChromiumブラウザコンポーネント(CefSharp)を使ってみる その２

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

前回の[WinFormsでChromiumブラウザコンポーネント(CefSharp)を使ってみる](https://qiita.com/yaju/items/97b61d0d8bc3f9ed044d)の続きです。

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

# URLの取得
現在表示しているURLを取得します。
WPFにはAddressプロパティがあるんですが、WinFormsには見当たらないんですよね。
[WPFでCefSharp（Chromiumの.NET向け実装）を使う - 1](https://qiita.com/GHKEN/items/d2d8b0745ef2622a2bbc)

なので、LoadingStateChanged イベントを使用して変数にセットして使用します。

```vb
Private _currentAddress As String

AddHandler _webBrowser.LoadingStateChanged, AddressOf OnLoadingStateChanged

Private Sub OnAddressChanged(sender As Object, e As AddressChangedEventArgs)
    _currentAddress = e.Address
End Sub
```

* [CEF browser can't find Address property - stackoverflow](https://stackoverflow.com/questions/53456372/cef-browser-cant-find-address-property)
* [Cefsharp how to get current URL address? c# - stackoverflow](https://stackoverflow.com/questions/44760073/cefsharp-how-to-get-current-url-address-c-sharp)

# URLの変更
メニュー(MenuStrip)にBMI項目を作成してBMIメニューをクリックしたら、体脂肪率サイトを表示するようにします。
![cefSample_Menu.png](https://qiita-image-store.s3.amazonaws.com/0/14053/eb090286-3a7e-381e-1107-63efac8f9ad1.png)

WinFormsでは、Loadメソッドを使用します。
WPFにはAddressプロパティがあるんですが、WinFormsには見当たらないんですよね。

```vb
Private Sub BMIToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BMIToolStripMenuItem.Click
    _webBrowser.Load("https://keisan.casio.jp/exec/system/1161228728")
End Sub
```

# ブラウザ読込完了時イベント
ブラウザ読込完了は OnLoadingStateChanged イベントを使用します。
IEのWebブラウザコンポーネントにあった DocumentCompleted イベントの代わり。
[CefSharp documentcompleted - stackoverflow](https://stackoverflow.com/questions/41985380/cefsharp-documentcompleted)

IsLoading が False になった時に読込完了処理を記述します。

```vb
AddHandler _webBrowser.LoadingStateChanged, AddressOf OnLoadingStateChanged

Private Sub OnLoadingStateChanged(sender As Object, e As LoadingStateChangedEventArgs)
    If Not e.IsLoading Then
```

# HTML要素の値セットとボタンクリック
HTML要素の値のセットやクリックは、EvaluateScriptAsync メソッドに 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();"
_webBrowser.ExecuteScriptAsync(jsScript)
```

# HTML要素の値の取得 
HTML要素の値の取得には EvaluateScriptAsync メソッドにメソッドチェーンで ContinueWith を使用して非同期成功時の処理を用います。

体脂肪率のDIVタグのIdは"ans1"となります。

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

```vb
jsScript = "document.getElementById('ans1').innerText;"
_webBrowser.EvaluateScriptAsync(jsScript).ContinueWith(
    Sub(x)
        Dim response = x.Result

        If response.Success AndAlso response.Result IsNot Nothing Then
            anser = response.Result.ToString()
            MessageBox.Show("BMI = " & anser)
        End If
    End Sub)
```

# 最終結果

```vb
Private Sub OnLoadingStateChanged(sender As Object, e As LoadingStateChangedEventArgs)
    If Not e.IsLoading Then
        ' 読込完了処理を記述
        Dim jsScript As String
        Dim anser As String = ""
        If _currentAddress.IndexOf("keisan") >= 0 Then
            jsScript = "document.getElementById('ans1').innerText;"
            _webBrowser.EvaluateScriptAsync(jsScript).ContinueWith(
                Sub(x)
                    Dim response = x.Result

                    If response.Success AndAlso response.Result IsNot Nothing Then
                        anser = response.Result.ToString()
                        If anser.Trim = "" Then
                            jsScript = String.Format("document.getElementById('var_身長').value = '{0}';", 180)
                            jsScript &= String.Format("document.getElementById('var_体重').value = '{0}';", 54)
                            jsScript &= "document.getElementById('executebtn').click();"
                            _webBrowser.ExecuteScriptAsync(jsScript)
                        Else
                            MessageBox.Show("BMI = " & anser)
                        End If
                    End If
                End Sub)
        End If
    End If
End Sub
```

![CefSample_keisan.png](https://qiita-image-store.s3.amazonaws.com/0/14053/dbd95bab-0510-9513-abc7-9ef78466cca0.png)

# 最後に
日本語による CefSharp のブログ記事はサイト表示して終わりが多くて、そこから先を知りたいんだけどねって感じですよ。結局は海外サイトを調べることになる。