- PR -

WebBrowser コントロールを使用し、URL を見ずにどの frame かを識別することは可能ですか?

投稿者投稿内容
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-03-11 15:55
.NET 2.0 で C# により WebBrowser コントロールを制御しています。(Windows XP Professional + Visual C# 2005 Express Edition を使用。)

フレーム構造になった Web ページにアクセスすると DocumentCompleted イベントが、フレームの構造に応じた回数分、発生しますが、何回目のイベントがどのフレームによるものかを識別することは可能ですか?

ちなみに、つぎのコードでは、
コード:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace TestApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            webBrowser1.Navigate(フレームになったページのURL);
        }

        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            Console.WriteLine("e.Url = " + e.Url);
        }
    }
}


イベント引数の WebBrowserDocumentCompletedEventArgs の URL を見れば、一応は識別します。実用上はこれで問題ないと思います。
しかし、極端な例ですが、たとえば左右に分割したフレーム構造で、右と左で URL が一緒というのも、ありえなくはないはずですが、そういう場合、URL 以外の情報を使って、フレームを識別することは可能でしょうか?
デバッガーで上記のコード中の変数 webBrowser1, sender, e の中をざっと見てみたのですが、そのような情報を見つけることができませんでした。

目的としては、今のところはそれほどフレームを識別したいわけではなく、要は、ページを更新した際に、最後の1回だけイベントを捕まえてページ解析の処理したいだけです。しかし、何度もイベントが来るのでなんども処理をせざるを得ず、困っています。
indigo-x
大ベテラン
会議室デビュー日: 2008/02/21
投稿数: 207
お住まい・勤務地: 太陽の塔近く
投稿日時: 2008-03-11 17:45
最後が分からないので、DocumentCompleted毎にタイマー時間を延長して

1分(?)たったら解析と言うのはどうでしょうか?


無理やり案ですが(やった事無いですが)
Proxyもどきを作成してWebBrowserのDocumentStreamに設定して
Open/Close等をカウントして終了検出
(Open/Closeが同数の話ですが、よく知らない、まとまる?)
ぴあちゃん
ぬし
会議室デビュー日: 2008/02/07
投稿数: 287
投稿日時: 2008-03-11 23:26
sender には何が来てます?
3分割の時、3つの異なるオブジェクトで来ますか?
ぴあちゃん
ぬし
会議室デビュー日: 2008/02/07
投稿数: 287
投稿日時: 2008-03-11 23:45
引用:

ぴあちゃんさんの書き込み (2008-03-11 23:26) より:
sender には何が来てます?
3分割の時、3つの異なるオブジェクトで来ますか?




3つかどうかはわからんのね。


コード:

Public Class Form1

Private WithEvents wb1 As New WebBrowser

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

wb1.Dock = DockStyle.Fill
Me.Controls.Add(wb1)

wb1.Navigate("C:\Documents and Settings\デスクトップ\HTML\FrameSet.html")

End Sub

Private Sub wb1_documentComp(ByVal s As Object, ByVal e As WebBrowserDocumentCompletedEventArgs) Handles wb1.DocumentCompleted

Console.WriteLine(s.ToString + "::" + e.Url.ToString)


End Sub
End Class




これで、確認しました。


コード:

<frameset rows="50,*">
<frameset cols="50,*">
<frame src="http://www.google.com">
<frame src="http://www.yahoo.co.jp">
</frameset>
<frame src="http://www.goo.ne.jp">
</frameset>


フレームのHTMLはコレ。

とりあえず、100回くらい起動してみたけど、全部最後のイベントのURLは
上記フレームのHTMLでしたよ。
最後の判定だけならこれだけで十分。

で、2つのフレームが同内容の時、どっちのイベントなのか?ですが、
同内容である意味が無いので、「知らない」ということで。



[ メッセージ編集済み 編集者: ぴあちゃん 編集日時 2008-03-11 23:46 ]
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-03-11 23:45
引用:

indigo-xさんの書き込み (2008-03-11 17:45) より:
最後が分からないので、DocumentCompleted毎にタイマー時間を延長して

1分(?)たったら解析と言うのはどうでしょうか?


高速に処理したいので、「待ち」は入れたくないと考えています。

引用:

indigo-xさんの書き込み (2008-03-11 17:45) より:
無理やり案ですが(やった事無いですが)
Proxyもどきを作成してWebBrowserのDocumentStreamに設定して
Open/Close等をカウントして終了検出
(Open/Closeが同数の話ですが、よく知らない、まとまる?)


これは分かりませんでした。Proxy とは HTTP Proxy という意味でしょうか?それともデザインパターンの Proxy パターンでしょうか?
ちなみに SSL のサイトや JavaScript がたくさん仕掛けられているようなサイトにもアクセスしたいので、あくまでも IE の持つ HtmlElement 等のオブジェクトをプログラムから操作する、というレベルでのアプリケーションを考えています。

引用:

ぴあちゃんさんの書き込み (2008-03-11 23:26) より:
sender には何が来てます?
3分割の時、3つの異なるオブジェクトで来ますか?


仕様は良くは知らないのですが、動かして見た限り、変数 sender には、どのフレームの時でも webBrowser1 と同じインスタンスが入っているようです。

たとえば、
コード:
        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (webBrowser1 == sender)
            {
                Console.WriteLine("同じ");
            }
            else
            {
                Console.WriteLine("違う");
            }
            Console.WriteLine("e.Url = " + e.Url);
        }


を動かすと、常に「同じ」が表示されます。
indigo-x
大ベテラン
会議室デビュー日: 2008/02/21
投稿数: 207
お住まい・勤務地: 太陽の塔近く
投稿日時: 2008-03-12 08:44
proxyの件あいまいですいません。

抽象的ですが。
 HTTPはpull型なので要求回数と結果回数が一致した場合終了を検知できると言う
 意味だったのですが、確認せず曖昧のままですいません。

で、確認したのですがNavigatedイベントがフレームでも要求前に動作するので

Naviagted回数とDocumentCompleted回数が同じ時に終了が確認できます。

(確認していないですが、一時的に同じ回数が発生する可能性?がある?)
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-03-12 14:06
引用:

indigo-xさんの書き込み (2008-03-12 08:44) より:
で、確認したのですがNavigatedイベントがフレームでも要求前に動作するので

Naviagted回数とDocumentCompleted回数が同じ時に終了が確認できます。

(確認していないですが、一時的に同じ回数が発生する可能性?がある?)


ありがとうございます。
ためしに、複雑なページを持つサイトで、あるフレームの中にあるボタンやリンクを押して、action 先の別のフレームを更新するようなことをしてみました。
Navigated と DocumentCompleted の発生回数をカウントしてみたのですが、カウントのしかたがマズいのかすぐにズレが生じてしまうようでした。
しかし、簡単なページだとズレないので、なにが原因でズレるのかを突き止めると、なにか掴めるかもしれないとも思っています。

ちなみに Navigated イベントを調べていたら、その前に発生する Navigation イベントのほうには、引数に frame の name が入っているようなので、これが使えないものかなとも思っています。
コード:
        private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            Console.WriteLine("Navigating = " + e.Url 
                + ", TargetFrameName = " + e.TargetFrameName + ", " + e.Cancel);
        }


みたいな感じで調べました。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-03-12 14:12
引用:

ぴあちゃんさんの書き込み (2008-03-11 23:45) より:
コード:
<frameset rows="50,*">
	<frameset cols="50,*">
		<frame src="http://www.google.com">
		<frame src="http://www.yahoo.co.jp">
	</frameset>
	<frame src="http://www.goo.ne.jp">
</frameset>


フレームのHTMLはコレ。

とりあえず、100回くらい起動してみたけど、全部最後のイベントのURLは
上記フレームのHTMLでしたよ。
最後の判定だけならこれだけで十分。


ありがとうございます。初回のアクセスだとおっしゃるような挙動のようです。
最初の質問で書かなくて申し訳ないのですが、最初にアクセスして得られたページの中にあるボタンやリンクを押して、ページを順次更新させたいと思っています。フレームAのボタンを押すと、フレームBが更新されたり、などのような感じです。
このような場合は、順序が不定になるような感じなので、残念ながらこの技が使えないと考えています。

スキルアップ/キャリアアップ(JOB@IT)