WebBrowserからWebView2へ(2)

WEBVIEW2を使用してみる(2)サイト遷移と待機処理

前回に続いて、早速表示させたブラウザコントロールのDOM操作を。。。
と思ったけどその前に。

機能的には「サイト遷移」→「遷移完了」→「DOM操作」と順序だてて処理させたいので、
まずは以下処理を非同期的に行えるようにしたいと思う。
・ ボタンをクリックしたら指定URLサイトへ遷移。
・ サイト遷移完了を待つ。

開発環境

・ Windows10
・ Microsoft Visual Studio 2019 (VB .NET)

サイト遷移

Navigateメソッドでサイト遷移を実行。このへんはWebbrowserコントロールと同じみたい。

webview.CoreWebView2.Navigate(“https://www.google.com”) 

完了待ち

前回作ったソースではWebView2のNavigationCompletedイベントで完了判定してたけど
今回は非同期で待機させたい+タイムアウト判定もしたい。

ということで色々調べてみたところ、すごい参考になるサイト様を発見。
とてもわかりやすい。欲しかった情報が豊富。ありがたい。ありがたい。
プログラムでネットサーフィン様

ざっくり書くと
・System.Threading.CountdownEventをつかう。
・condition.waitでイベント発生待ち
・NavigationCompletedイベントが発生したらcondition.Signal()でシグナル状態となり
 Wait解除(待機完了)。そのあとcondition.Reset()でシグナル状態解除。

Private ReadOnly condition As New System.Threading.CountdownEvent(1)

サンプルコード

せっかくならWebView2もいろいろカスタムしたいので、今回から継承クラス作成。
ClsWebView.vb

Imports Microsoft.Web.WebView2.Core
Imports Microsoft.Web.WebView2.WinForms

''' <summary>
''' WebView2を継承していろいろカスタマイズするクラス
''' </summary>
Public Class ClsWebView
    Inherits WebView2

    ''' <summary>
    ''' 列挙体: サイト遷移の状態判定用
    ''' </summary>
    Public Enum NAVIGATE_STATUS
        Navigating
        Complate
        NavigateError
        TimeoutError
    End Enum

    ''' <summary>
    ''' プロパティ: サイト遷移の状態
    ''' </summary>
    Private _status As NAVIGATE_STATUS = NAVIGATE_STATUS.Navigating
    Public ReadOnly Property NowStatus
        Get
            Return _status
        End Get
    End Property

    Private ReadOnly condition As New System.Threading.CountdownEvent(1)

    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    Public Sub New()

        '初期化
        InitializeAsync()

        '読込み完了時イベントを設定
        AddHandler Me.NavigationCompleted, AddressOf MeNavigationCompleted

    End Sub

    ''' <summary>
    ''' WebView2の初期化
    ''' </summary>
    Async Sub InitializeAsync()
        Await Me.EnsureCoreWebView2Async(Nothing)
    End Sub


    ''' <summary>
    ''' サイト表示完了までの待機処理
    ''' </summary>
    ''' <returns></returns>
    Public Async Function WaitNavigating() As Task(Of NAVIGATE_STATUS)

        '非同期実行
        Await Task.Run(
            Sub()
                '読み込み完了まで待機
                If condition.Wait(5000) Then
                    '待機完了
                Else
                    '待機未完了(タイムアウト)
                    Me._status = NAVIGATE_STATUS.TimeoutError
                End If
            End Sub
        )
        Return Me.NowStatus

    End Function


    ''' <summary>
    ''' URL読み込み完了時イベント
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub MeNavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs) Handles Me.NavigationCompleted

        If e.IsSuccess Then
            Me._status = NAVIGATE_STATUS.Complate
        Else
            Me._status = NAVIGATE_STATUS.NavigateError
        End If

        condition.Signal()
        System.Threading.Thread.Sleep(1)
        condition.Reset()

    End Sub

End Class


フォームにはボタンとWebView2継承クラスを設置
Form1.vb

Public Class Form1

    ''' <summary>
    ''' フォームロード
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Try

            'ボタン作成 + コントロール配置
            Dim navigateBtn As Button = New Button()
            Me.Controls.Add(navigateBtn)
            navigateBtn.Text = "サイト遷移"
            navigateBtn.Left = 0
            navigateBtn.Top = 0
            navigateBtn.Width = 100
            navigateBtn.Height = 30

            'WebViewオブジェクト作成 + コントロール配置
            Dim webview As ClsWebView = New ClsWebView()
            Me.Controls.Add(webview)
            webview.Name = "WebViewSample"
            webview.Left = 0
            webview.Top = 0 + navigateBtn.Height
            webview.Width = Me.Width
            webview.Height = Me.Height - navigateBtn.Height

            InitializeComponent()

            'イベント設定:メインフォームのサイズ変更時にWebViewも変更
            AddHandler Me.SizeChanged, Sub()
                                           webview.Width = Me.Width
                                           webview.Height = Me.Height - navigateBtn.Height
                                       End Sub

            'イベント設定:ボタンクリック時、サイト遷移開始
            'ボタンクリック後のフリーズを避けるため非同期で実装
            AddHandler navigateBtn.Click,
                Async Sub()

                    '初期化終えてから処理
                    If webview Is Nothing OrElse webview.CoreWebView2 Is Nothing Then
                        MsgBox("コントロール初期化中です")
                        Exit Sub
                    End If

                    '指定URLへ遷移
                    webview.CoreWebView2.Navigate("https://www.google.com")

                    '待機処理
                    Await webview.WaitNavigating

                    '遷移完了後のURLとステータスをデバッグ出力
                    Debug.Print("URL:" & webview.Source.OriginalString & " | STATUS:" & webview.NowStatus)

                    'ためしに、もう一回別のURLへ遷移
                    webview.CoreWebView2.Navigate("https://www.yahoo.co.jp")
                    Await webview.WaitNavigating
                    Debug.Print("URL:" & webview.Source.OriginalString & " | STATUS:" & webview.NowStatus)

                End Sub

        Catch ex As Exception
            Debug.Print("[Error] : " & Now & " : " & ex.ToString)
        End Try

    End Sub

End Class

Googleさんへサイト遷移完了あとにYahooさんへ遷移しました。

つぎはようやくDOM操作にはいります。

タイトルとURLをコピーしました