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操作にはいります。