tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルVB WebBrowserでページの切り替えが思うように出来ない
記事No11470
投稿日: 2015/08/14(Fri) 15:11
投稿者まつ
いつもお世話になっております。

VB2015を使用しています。

WebBrowserでWebページを切り替えながらHTMLを取得するコードを
作成しています。

下記コードのようにループでページを切り替える方法がうまく
いきません。
ページを切り替えるごとにHTMLを取得したいのですが,
Button1.Clickイベントが終わらないと全てのHTMLを取得出来ません。
なぜかNavigateの後にMsgBoxを入れるとその時点でページが変わり
HTMLを取得出来ます(MessageBox.Showでも可能)。
MsgBoxに似たイベントを発生させてページを自動的に切り替える方法
は無いでしょうか?
なお,EventArgsで空のイベントを発生させてみましたがダメでした。

仕方が無いので現状では順次タイマーイベントを発生させて都度HTML
を取得する方法で目的を達成していますがコードが煩雑のため単純
ループのような簡単な方法に変更したいです。

他,New WebBrowser で都度インスタンスを生成,Disposeする方法
があると思いますがログインしてセッションを保ったままページを
切り替えたいため,この方法は使えません。

Public Class Form1
  Private Sub Button1_Click(sender …) Handles Button1.Click

    Dim myUrl As String = Nothing

    For i As Integer = 1 To 2
      If i = 1 Then myUrl = " ttp://….co.jp/1.html"
      If i = 2 Then myUrl = " ttp://….co.jp/2.html"
      WebBrowser1.Navigate(myUrl)
      'MsgBox("読み込み")  'MsgBoxがあるとその時点で読み込まれる
    Next

  End Sub

  Private Sub WebBrowser1_DocumentCompleted(ByVal sender As Object,
                 ByVal e As WebBrowserDocumentCompletedEventArgs) _
                              Handles WebBrowser1.DocumentCompleted

    If e.Url = DirectCast(sender, WebBrowser).Url Then
      Dim html As String = WebBrowser1.Document.Body.InnerHtml
      Console.WriteLine(html)
    End If

  End Sub
End Class

[ツリー表示へ]
タイトルRe: VB WebBrowserでページの切り替えが思うように出来ない
記事No11471
投稿日: 2015/08/14(Fri) 19:18
投稿者魔界の仮面弁士
> 下記コードのようにループでページを切り替える方法がうまく
> いきません。
アプリケーションがアイドル状態に入らないと、
WebBrowser がページを処理できないためです。

今回の件に限った話ではありませんが、
コントロールのイベント(Button1_Click など)には、
時間のかかる処理を書かないようにしましょう。



> なぜかNavigateの後にMsgBoxを入れるとその時点でページが変わり
> HTMLを取得出来ます(MessageBox.Showでも可能)。
メッセージボックスの表示中は、
 「他に処理が行われておらず、ユーザーからの操作を待っている状態」
にあたります。このため、アプリケーションがアイドル状態になったことで、
WebBrowser の処理を実行できる余裕が生まれたわけです。


> 順次タイマーイベントを発生させて
タイマー利用時は、どのように処理させましたか?


> コードが煩雑のため単純ループのような簡単な方法に変更したいです。
Timer の場合、タイマー通知は非同期的に行われますよね。
Start メソッドで呼びだした後、最初の Tick イベント発生までには、Interval 以上の時間を要します。

WebBrowser の場合も同様に、処理が非同期的に行われます。
Navigate メソッド呼びだし後、DocumentCompleted イベント発生までにはある程度の時間を要します。


使用しているオブジェクトが違うだけで、処理の流れとしては同じことです。



Public Class Form1
    Private urlList As New List(Of String)()
    Private urlIndex As Integer = -1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        urlList.Add("http://www.google.co.jp/")
        urlList.Add("http://www.microsoft.co.jp/")
        urlList.Add("http://www.apple.co.jp/")
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Button1.Enabled = False

        urlIndex = 0
        Dim url As String = urlList(urlIndex)
        WebBrowser1.Navigate(url)
    End Sub

    Private Sub WebBrowser1_DocumentCompleted(sender As Object, _
            e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted

        Debug.WriteLine("===============" & e.Url.ToString())
        Debug.WriteLine(WebBrowser1.DocumentText)

        urlIndex += 1
        If urlIndex < urlList.Count Then
            Dim url As String = urlList(urlIndex)
            WebBrowser1.Navigate(url)
        Else
            urlIndex = -1
            Button1.Enabled = True
        End If
    End Sub
End Class

たとえば上記では、Button1_Click で Navigate した後、
直ちに End Sub に到達しているため、その時点でアイドル状態に入ります。
これならば、DocumentCompleted のイベントが発生すると思いますよ。





上記の Enumerator 版。
Enumerator は「For Each〜Next」時に内部で利用されているものですが、
管理としてはこちらの方が楽かもしれません。


Public Class Form1
    Private urlList As New List(Of String)()
    Private nextUrl As List(Of String).Enumerator

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        urlList.Add("http://www.google.co.jp/")
        urlList.Add("http://www.microsoft.co.jp/")
        urlList.Add("http://www.apple.co.jp/")
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Button1.Enabled = False

        nextUrl = urlList.GetEnumerator()
        WebBrowser1.Navigate(nextUrl.Current)
    End Sub

    Private Sub WebBrowser1_DocumentCompleted(sender As Object, _
            e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted

        Debug.WriteLine("===============" & e.Url.ToString())
        Debug.WriteLine(WebBrowser1.DocumentText)

        If nextUrl.MoveNext() Then
            WebBrowser1.Navigate(nextUrl.Current)
        Else
            Button1.Enabled = True
        End If
    End Sub
End Class

[ツリー表示へ]
タイトルRe^2: VB WebBrowserでページの切り替えが思うように出来ない
記事No11472
投稿日: 2015/08/15(Sat) 12:13
投稿者まつ
魔界の仮面弁士様

いつも迅速で的確なアドバイスをありがとうございます。

ご指南頂きましたコードで目的の動作を確認しました。早速活用
させて頂きます。

DocumentCompleted側でNavigateさせる方法は以前に試して動作
しませんでした。何か記述ミスがあったようです。

タイマーイベントでのコードを載せます。手元に実際のコードが
無くて,こんな感じだったかなと記述したものです。
NavigateのたびにタイマーのEnabledをオンオフさせています。

助かりました。今後とも宜しくお願い致します。

Public Class Form1

  Private count As Integer
  Private myUrl As String
  Private webGet As New Timers.Timer()

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    AddHandler webGet.Elapsed, AddressOf webGet_Event
  End Sub

  Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Button1.Enabled = False
    webGet.Interval = 100
    webGet.Enabled = True
  End Sub

  Private Sub webGet_Event(ByVal source As Object,
                     ByVal e As System.Timers.ElapsedEventArgs)
    webGet.Enabled = False
    If count = 0 Then myUrl = " http://www.google.co.jp/"
    If count = 1 Then myUrl = " http://www.microsoft.co.jp/"
    If count = 2 Then myUrl = " http://www.apple.co.jp/"
    WebBrowser1.Navigate(myUrl)
  End Sub

  Private Sub WebBrowser1_DocumentCompleted(ByVal sender As Object,
                 ByVal e As WebBrowserDocumentCompletedEventArgs) _
                              Handles WebBrowser1.DocumentCompleted
    If e.Url = DirectCast(sender, WebBrowser).Url Then
      Dim html As String = WebBrowser1.Document.Body.InnerHtml
      Console.WriteLine(html)
      If count < 3 Then
        count += 1
        webGet.Enabled = True
      Else
        Button1.Enabled = True
      End If
    End If
  End Sub

End Class

[ツリー表示へ]