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

IHTMLElement(IHTMLSelectElement)でOnChangeをシミュレートする方法

環境/言語:[WindpwsXP Pro Visual Basic.net2003 ]
分類:[.NET]

こんにちは、いつもお世話になっております。
MSHTMLでの情報が少なく、苦労しております。申し訳ありませんがご存知の方がおられたらご教唆ください。

(1)HTML上のボタンに対してClickをシミュレートする方法はIHTMLElementオブジェクトのClickコマンドで可能だと思います。

(2)HTML上のコンボボックスにOnChangeがついている場合、コンボボックスのセレクトをシミュレートする方法は、IHTMLSelectElementにキャストして、valueプロパティに値を設定することで可能だと思います。

(3)しかしながら、このvalueプロパティに値を設定してもOnchangeイベントは発動してないように見えます。念のため、selectedIndexプロパティに値を設定しても結果は同じでした。

(4)Onchangeの際には、サーバ側の関数を呼ぶ処理が入っていますが、サーバの関数の結果と思しき内容は(3)の設定処理以降も発生してないようです。

(5)最終的な対策として、submitのボタンを押すシミュレートを考えておりますが、それ以外によい方法がないかと思い、質問させていただきました。

お忙しいところ申し訳ありませんが、ご教唆ください。
> (1)HTML上のボタンに対してClickをシミュレートする方法はIHTMLElementオブジェクトのClickコマンドで可能だと思います。
それでOKです。(Clickコマンド → click メソッドですね)

> (2)HTML上のコンボボックスにOnChangeがついている場合、コンボボックスのセレクトをシミュレートする方法は、IHTMLSelectElementにキャストして、valueプロパティに値を設定することで可能だと思います。
コンボボックスというのは、<select>要素の事ですよね。
となると、value ではなく、selectedIndex の方が良いでしょう。

> (3)しかしながら、このvalueプロパティに値を設定してもOnchangeイベントは発動してないように見えます。念のため、selectedIndexプロパティに値を設定しても結果は同じでした。
その場合、onchangeイベントは連動しません。

強制的に実行させるなら、onchangeプロパティに割り当てられた
関数オブジェクトを直接 Call するか、もしくは、fireEvent メソッドを
呼び出すようにしてみてください。

> (4)Onchangeの際には、サーバ側の関数を呼ぶ処理が入っていますが、サーバの関数の結果と思しき内容は(3)の設定処理以降も発生してないようです。
サーバ側の処理という事は…ajax という事ですか? それとも PostBack?

> (5)最終的な対策として、submitのボタンを押すシミュレートを考えておりますが、
その場合は、<form>要素のsubmitメソッドを呼び出す事になりますね。
もしくは、<input type="submit"> や <input type="image"> の
click メソッドでも良いでしょう。
魔界の仮面弁士さん ご返答ありがとうございます。

selectedIndex採用しました。現在相手にしているのはAjaxではありません。
PostBackだと思います。

私としては、お勧めいただいた
> 強制的に実行させるなら、onchangeプロパティに割り当てられた
> 関数オブジェクトを直接 Call するか、もしくは、fireEvent メソッドを
> 呼び出すようにしてみてください。

を考えたいのですが、これは
Selectタブのonchangeメソッドの内容を取得するということでしょうか。FireEventを調べて見ましたが、VB.netでの記事がなく困っています。
以下のonchangeの値がDBNULLでない場合に処理をしようと思っておりますが、
そのときのOnChangeメソッドの中身はSystem.__ComObjectが入っておりうまくキャストできませんでした。

FireEventか関数CALL関する記事を教えていただければ幸いです。

Dim elmsAll As mshtml.IHTMLElementCollection = CType(HTMLBodyのオブジェクト.all,mshtml.IHTMLElementCollection)
Dim wElmClass As mshtml.IHTMLElement
Dim wElmSelect As mshtml.IHTMLSelectElement

For Each wElmClass In elmsAll
  Select Case wElmClass.tagName.ToUpper
  Case "SELECT"
    wElmSelect = wElmClass

    If wElmSelect.value <> wElm.value Then
      wElmSelect.selectedIndex = (設定するインデクス)
      If Not wElmSelect.onchange Is System.DBNull.Value Then
        ↓
        ここのonchangeメソッドはSystem.__ComObjectになっています
        ↑
      End If
    End If
  End Select
Next
> VB.netでの記事がなく困っています。
無理に VB.NET の記事を探すのではなく、mshtml 自体の仕様を参照した方が
良いかも知れません。

元の資料が他の言語向けの物であったとしても、mshtml 自体は ActiveX なので、
COM Interop の動作をある程度把握しておけば、他の言語向けの資料……たとえば
JScript 向けに DHTML 関連の記事など……も役立てる事ができます。


> FireEventか関数CALL関する記事を教えていただければ幸いです。

wElmSelect.fireEvent("onchange")
または、
CallByName(wElmSelect.onchange, Nothing, CallType.Method)
ですね。


> HTMLBodyのオブジェクト.all
.all を回して探すのではなく、getElementsByTagNameメソッドを使った方が、
効率が良いかと思いますよ。


> ここのonchangeメソッドはSystem.__ComObjectになっています
onchangeメソッド → onchangeプロパティですね。


ちなみに、onchangeに指定できるのは、スクリプトだけではありません。
たとえば、
 Class Foo
  <DispId(0)> Function Bar() As Object
   Return MessageBox.Show("TEST")
  End Function
 End Class
といったクラスを作り、それを VB.NET 側から
  wElmSelect.onchange = New Foo()
のように割り当てておけば、<select>要素を操作するたびに、
MessageBox.Show("TEST") のコードが実行される事になります。蛇足までに。
魔界の仮面弁士さん ご回答ありがとうございます。
いろいろ情報をいただきありがとうございました。
大変参考になりました。

最終的に、以下のロジックで解決しましたので、掲載します。

Dim elmsAll As mshtml.IHTMLElementCollection = CType(HTMLBodyのオブジェクト.all,mshtml.IHTMLElementCollection)
Dim wElmClass As mshtml.IHTMLElement
Dim wElmSelect As mshtml.IHTMLSelectElement

For Each wElmClass In elmsAll
  Select Case wElmClass.tagName.ToUpper
  Case "SELECT"
    wElmSelect = wElmClass

    If wElmSelect.value <> wElm.value Then
      wElmSelect.selectedIndex = (設定するインデクス)
      If Not wElmSelect.onchange Is System.DBNull.Value Then
        '↓
        wElmSelect.fireEvent("onchange")
        '↑
      End If
    End If
  End Select
Next
解決済み!

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