DOBON.NET DOBON.NETプログラミング掲示板過去ログ

WebBrowserでDocumentCompletedがたくさん発生

分類:[(未選択)]

[win2kpro+VC#2005Express]

GotDotNet
第 21 回 タブ表示型ブラウザをつくろう
http://www.gotdotnet.com/japan/student/column/firststep/firststep21.aspx

この記事を参考に簡単なタブブラウザを作ろうとしました。

フォームにTextBox、Button、TabControlを一つずつ貼り付け、
button1_Clickイベントハンドラに以下のコードを書きました。

this.SuspendLayout();

WebBrowser webBrowser = new WebBrowser();
TabPage tabPage = new TabPage();

webBrowser.Dock = DockStyle.Fill;
webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
tabPage.Controls.Add(webBrowser);
this.tabControl1.Controls.Add(tabPage);
this.tabControl1.SelectedTab = tabPage;
this.currentTabPage = tabPage;
this.currentWebBrowser = webBrowser;
webBrowser.Navigate(textBox1.Text);

this.ResumeLayout(false);
}

また、以下のイベントハンドラも追加しました

void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
i++;
Console.Write("{0}\r\n",i);
}

コンパイル後実行し、TextBoxに
http://www.codeproject.com/csharp/multitabwebbrowser.asp
(適当なページです)と入力し、
Buttonをクリックすると、
出力ウィンドウに
1
2
と表示されました。
ためしにButtonを5回連続でクリックしてみると
1
2
3
と続き
16
までいきました。

WebBrowserコントロールのDocumentCompletedイベントは、
ページを読み終えた瞬間に発生するとヘルプにありました。
しかし、どうして上記のような現象が起きてしまうのでしょうか?

www.google.co.jp
で実験してみると、ちゃんと1になりました。
連続でクリックしても12345となりました。
原因を究明しようと
http://www.codeproject.com/csharp/multitabwebbrowser.asp
のページをIEで開き、右クリックしてソース表示しようとしたら、
なぜかエディタが開きませんでした。

ひょっとしてフレームが関係しているのでしょうか?
だとしたら、ページ一つが読み込まれたことを確認するには
どのような実装が考えられるでしょうか?
よろしくお願いいたします。
2006/04/22(Sat) 17:53:16 編集(投稿者)

ページにフレームがあると,フレーム毎にDocumentCompletedが発生します。

e.Urlはフレームのアドレスが返されます。
一方DirectCast(sender,WebBrowser).Urlはナビゲートしたアドレスが返されます。

また,ナビゲートしたアドレスのページは最後に読み込まれます。

よって全てのフレームが読み込まれたかどうかは次のようなコードで判定できると
思います。

If e.Url = DirectCast(sender, WebBrowser).Url Then
Debug.Print("ページ読み込み完了")
End If
お返事ありがとうございます。

C#にはDirectCastがないようなので、

void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{

if (e.Url.ToString() == ((WebBrowser)sender).Url.ToString())
{
Console.Write("ドキュメント読み込み完了");
}

}

としてみたのですが、ifの中は実行されませんでした。
何が起こっているのか調べるために

void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

{
 i++;
Console.Write("{0}{1}\r\n",i,e.Url);
}

としてみると、

0最初のフレーム(本当はurlです)
1次のフレーム

となりました。

どうやら、

> 一方DirectCast(sender,WebBrowser).Urlはナビゲートしたアドレスが返されます。

((WebBrowser)sender).Urlは確かにナビゲートしたアドレスを返します。
しかし、

> また,ナビゲートしたアドレスのページは最後に読み込まれます。

これがどうやら読み込まれていないようです。
サイトAへ飛ぶとき、サイトAはフレームで構成されていて、ページBとCを含んでいるとすると、
0ページBのアドレス
1ページCのアドレス
まではいきますが、
2サイトAのアドレス
とはならないようです。
調べてみます。
フレームセットAがフレームB,フレームCを含んでいるとき,フレームCの
リンクをクリックしてフレームDに移動したときなどはフレームセットAの
DocumentCompletedは発生しないと思います。

WebBrowser.Navigate(フレームセットA)で移動したときはAのDocumentCompletedが
発生するはずです。
> WebBrowser.Navigate(フレームセットA)で移動したときはAのDocumentCompletedが
> 発生するはずです。
>

再度のご回答ありがとうございます。

<frameset>タグを使ってtest.htmlを作り、
実験してみるとおっしゃる通り一番最後に
フレームセットを記述しているhtmlファイ
ルのアドレスが返されます。

どうやら適当に選んだ最初の
http://www.codeproject.com/csharp/multitabwebbrowser.asp
というファイルが何か特殊な事情を生じさせているようです。

一番最後に発生したWebBrowser_DocumentCompletedイベントの
e.Urlの値が、WebBrowser.Navigate()で指定したアドレスでは
ないということから、どうやらこのページはフレームで構成されて
いるわけではないようです。

ファイルの拡張子が.aspとなっていることからASPを使った動的な
ページだと思うのですが、ASPがさっぱりわかりません。
ASPとDocumentCompletedイベントの間に何か関係があるのだと
思うのですが、
例えば、ASPで構成したページ中に、別のファイルからデータを
取り込んで表示させたり、別のスクリプトを呼び出してその結果
を取り込んだりした際にもDocumentCompletedイベントが発生
しているのかもしれませんが、ちょっとこれ以上は今の僕の知識
ではどうにもなりそうにもありません。

ありがとうございました。

通りすがりです。

現象を見ててふと思ったのですが、
以下の方法で出来ないでしょうか?

最初のaxWebBrowser1_DocumentCompleteイベントで、
ブラウザコントロールのdoc.innerHtmlを取得します。

取得したdoc.innerHtmlの値(HTMLソース)を見て
フレーム(FRAMEタグorIFRAMEタグ)が幾つあるかを数えます。

あとは、その数だけDocumentCompleteイベントが発生したら
ページをすべて読み込んだ
ということにするのはどうでしょうか?

ちなみに
http://www.codeproject.com/csharp/multitabwebbrowser.asp
のサイトでは、フレーム(IFRAMEタグ)が6つあることが分かるので、
最初のDocumentCompleteイベントでIFRAMEタグの数を数えてやれば
上記方法でいけそうです。

普通のフレーム対応のページでも同様の方法で
出来ました。

不特定多数のページで試したわけではないので、
全てに対応できるかは分かりませんが・・。

HTMLソース(doc.body.innerHTML)の取得方法は
以下のようにすれば出来ます。

mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)axWebBrowser1.Document;
String document=doc.body.innerHTML;

*参照の追加でMicrosoft.mshtmlの追加が必要
> String document=doc.body.innerHTML;
stringでした (*^^*

DOBON.NET | プログラミング道 | プログラミング掲示板