- - PR -
C# で COM の WebBrowser を使って mshtml で制御する際に、イベントハンドラーの設定方法が分からない
1
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2009-01-19 01:29
フォームを持った Windows アプリケーションで C# から IE(WebBrowser) を制御しています。
私の知識では、このような制御のやりかたにはつぎの2つに大別できると思っています。 (1) System.Windows.Forms 名前空間の WebBrowser クラスを使い、HTML の解析もこの名前空間のクラス(HtmlDocument/HtmlElement クラスなど)を使うやりかた。 (2) COM の SHDocVw.DLL(Microsoft Internet Controls) MSHTML.DLL(Microsoft HTML Object Library) の2つを参照設定し、Interop.SHDocVw の WebBrowser クラスを使い、HTML の解析は Microsoft.mshtml 名前空間のクラスを使うやりかた。 ここで(2)の mshtml を使う場合、HTML 要素にイベントハンドラーを設定するやりかたが分かりません。 ちなみに、(1)の System.Windows.Forms を使うやりかたはできています。つぎの擬似コードのような感じです。
これを(2)用に書き直したいのですが、まず、どのプロパティーやメソッドを使えば良いのかが分かりません。値が変わったことをイベントとして捕まえたいので onpropertychange プロパティーを使えば良いのかとも思ったのですが、実際に代入してみようと試しに null を代入(set)すると、もうそれだけで NotImplementedException が起きてしまいます。ちゃんとしたイベントハンドラーを代入してもおそらくはじかれるように思います。 attachEvent メソッドという、それっぽい名前のメソッドもあるのですが、こっちは(1から数えて)2番目の引数にイベントハンドラーをどう書けば良いのかが皆目見当が付きません。 以下に、(2)のこれらを試行錯誤した擬似コードを示します。
ちなみに VB(VB6やそれ未満) だったら、(2)と同等のことは、とくに悩まなくてもIDE上で簡単にイベントハンドラーの設定ができ、ちゃんと動かすことができた記憶があります。 今回はこれと同じことを .NET(C#) でやりたいです。 なお(1)も(2)も、上記のコードは雰囲気を示す擬似コードです。完全なサンプルコードを提示しようかとも思ったのですが、ちょっと大変だったのでやめましたが、リクエストがあれば言ってください。(ちゃんとできるかどうかは分かりませんが。) | ||||||||||||
|
投稿日時: 2009-01-19 12:25
第3の方法 System.Windows.Forms 名前空間の WebBrowser クラスを使う。 HTML の解析は Microsoft.mshtml 名前空間のクラスを使う。 http://msdn.microsoft.com/ja-jp/library/system.windows.forms.htmldocument.domdocument.aspx
Visual C# .NET アプリケーションでドキュメント イベントを処理する方法 http://support.microsoft.com/kb/312777/ja を真似すると、HTMLElementEvents2_Eventインターフェースのonpropertychangeイベントかな? | ||||||||||||
|
投稿日時: 2009-01-20 00:43
todoさん、こんにちは。
ご回答ありがとうございます。
なるほど、こういうやりかたもあるのですね。
これを今、試しています。 まず、このページのサンプルどおりのことは動かすことができました。こういうふうに使うんですね。このサンプルですごく助かりました。 つぎに、特定の HTML 要素(input タグなど)だけに onpropertychange イベントのイベントハンドラーを設定してみましたが、なんとなくうまく動くような感じがします。
ただ、mshtml はクラスの種類が異様に多く、デバッガーで一時停止しながらソースコードを書き換えて、どのクラスを使えば良いか試行錯誤しながらやっています。もしも Visual Studio のこの機能(デバッグ時にソースコードを書き換えることができる機能)がないと辛いところです。 ちなみに Visual Studio で、ソースコードを書くときに += を入力すると、イベントハンドラーが自動生成される機能が使えるので、それも便利です。 なお、もうひとつ大きな問題が残っていて、なぜか簡単なサンプルコードなら動くのですが、自分が開発している大きなコードに組み込むと、実行時にエラーは出ないもののイベントがまったく発生しなくなってしまい、悩んでいます。 とりあえず途中経過報告まで。 | ||||||||||||
|
投稿日時: 2009-01-20 21:57
この件についてですが、その後、試行錯誤してみたところ、私が前回書いたコードで言うと、変数 iEvent をローカル変数にしているだけだとダメみたくて、インスタンス変数(メンバー変数)などにして保持しておく措置が必要なように感じました。 まだちょっとあやふやな見解ですが、こうすれば確実にイベントが起きるけど、こうしないとほとんどイベントが起きないような感じがします。大きなコードに組み込むと動かなくなるのも、ガーベッジコレクションの頻度の違いのためなのでしょうか? 私は .NET で COM を使った経験がなくて、この辺の知識がないのですが、本当にこの措置は必要なのでしょうか? ちなみに、 http://support.microsoft.com/kb/312777/ja のサンプルでも、これと同様の目的として使っている変数 iEvent は、ローカル変数にしています。これはすなわち axWebBrowser1.Document なので、わざわざ別に保持する必要性はないのかもしれませんが、厳密には、アプリケーションプログラムの側で明示的に保持するべきなのでしょうか? | ||||||||||||
|
投稿日時: 2009-01-29 22:37
古い話ですが、これについてはやはりこの推測のとおりのようです。自分のメモついでに掲示板にも書かせていただきます。 まとめとして、以下に再現コードを示します。
の Windows Application で、つぎのようなページにアクセスします。 hoge.html はつぎのような内容です。
このページは1秒おきに input 要素(id=bar)の value が変わるような例です。この変化を onpropertychange で捕まえます。 button1 を押すとページに Navigate して、button2 を押すと onpropertychange のイベントハンドラーが設定されます。 これを動かすと、実行環境にもよるのですが、1〜2回ぐらいのイベントを捕まえた後、すぐにイベントが捕まえられなくなるときもあれば、100回以上大丈夫なときもあります。ウィンドウをマウスでごにょごにょいじっていると止まりやすくなります。 上記でコメントになっている行を有効にしてメンバー変数(フィールド)に保持するようにすれば、イベントの発生が止まることはなくなります。 以下は私の推測ですが、これは別段 COM だからというわけではなく、.NET の段階でもすでにあたりまえのことのようです。 件名:「Timer()クラスについて」 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=38912&forum=7 なども参考にさせていただきました。 |
1