WebControlのラジオボタンを押した等のイベントをVBで拾うには

解決


HTMLって難しいんですね  2004-07-06 17:25:54  No: 114575  IP: [192.*.*.*]

VBのフォーム上に貼られたWebBrowserコントロール内に配置したラジオボタンを選択したときにそれをイベントとしてVB側で取得したいのですが、良い方法を見つけられません。このような処理は可能なのでしょうか?

編集 削除
HTMLって難しいんですね  2004-07-06 17:27:00  No: 114576  IP: [192.*.*.*]

タイトル間違っちゃいました。WebBrowserでした。すみません。

編集 削除
魔界の仮面弁士  2004-07-06 22:01:28  No: 114577  IP: [192.*.*.*]

対象のラジオボタンオブジェクトのイベントで処理できますよ。
onfocus イベントとか、onclick イベントとか、onchangeイベントとか…。

なお、WebBrowser1.documentから、処理対象のラジオボタンを
取得する方法に付いては、過去ログを参照してみてください。

編集 削除
HTMLって難しいんですね  2004-07-07 09:39:15  No: 114578  IP: [192.*.*.*]

ご回答ありがとうございます。処理対象となるラジオボタンを取得することはできたのですが、それを選択することによるイベントをどうプログラムしていいかわからず悩んでおります。いわゆるprivate sub イベント  みたいな書き方とは違ってくるのでしょうか?

編集 削除
HTMLって難しいんですね  2004-07-07 11:37:43  No: 114579  IP: [192.*.*.*]

具体的に書くとVBでラジオボタンがいっぱいのHTMLファイルを作成し、WebBrowserに表示させています。で、あるラジオボタンが押されたタイミングでVBにHTMLファイルを再作成させてWebBrowserに再表示させられれば理想的だと考えています。

編集 削除
魔界の仮面弁士  2004-07-07 14:42:43  No: 114580  IP: [192.*.*.*]

例えば、クラスモジュール Class1 を追加して、以下のような記述を行います。

Option Explicit
Public Sub MyMethod()
    MsgBox "イベント発生"
End Sub

さらに、[ツール]-[プロシージャ属性]のメニューを使って、
この MyMethod の「プロシージャID」を、「(既定値)」に変更します。

あとは、フォーム側で、
Option Explicit
Private Sub Form_Load()
    WebBrowser1.Navigate2 "http://www.google.co.jp/"
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    Set WebBrowser1.Document.f.lr(0).onclick = New Class1
    Set WebBrowser1.Document.f.lr(1).onclick = New Class1
End Sub

などとすればOKです。VBScriptでいう AddRef関数のイメージですかね。


あるいは、MSHTML.TLB ファイルを参照設定しておき、
WithEventsな変数で受けるという手もあります。

編集 削除
魔界の仮面弁士  2004-07-07 14:48:07  No: 114581  IP: [192.*.*.*]

> VBScriptでいう AddRef関数のイメージですかね。
「GetRef関数」の間違いです。m(_ _)m

編集 削除
HTMLって難しいんですね  2004-07-07 15:00:15  No: 114582  IP: [192.*.*.*]

魔界の仮面弁士さん。ご教授ありがとうございました。
早速上記でためしてみましたが・・・
>Set WebBrowser1.Document.f.lr(0).onclick = New Class1
のところで実行時エラーが出てしまいました。何が足りないのでしょうか(泣)

編集 削除
HTMLって難しいんですね  2004-07-07 15:07:10  No: 114583  IP: [192.*.*.*]

それとは別に
> あるいは、MSHTML.TLB ファイルを参照設定しておき、
> WithEventsな変数で受けるという手もあります。
こちらで挑戦していたのですが、やはりうまく動きません。
Private WithEvents WBEvent As MSHTML.HTMLDocument
と宣言して、DocumentCompleteイベントにて
Set WBEvent = WebBrowser1.Documentとすることで
onclickやonmousedown、onmouseup等を使えるようにはなりました。
ただWebBrowser1に対してであり、その中のラジオボタンの状態は
そのイベントごとに拾うような形にしかできていません。
WebBrowser1内のあるラジオボタンのグループに対して
イベントを持つようなことは無理なのでしょうか?
またonclickをソースに書くとWebBrowser1内のラジオボタンに
色がつかなくなってしまったのですが、これは一体・・・!?

編集 削除
HTMLって難しいんですね  2004-07-07 17:26:17  No: 114584  IP: [192.*.*.*]

自己レスでスミマセン!!
> またonclickをソースに書くとWebBrowser1内のラジオボタンに
> 色がつかなくなってしまったのですが、これは一体・・・!?
onclickイベントを通ると、選択したラジオボタンがChecked=False
になってしまっていました。なんとかTrueのまま残したいのですが
何か良い方法がありましたら併せて教えていただけませんでしょうか。
よろしくお願いいたします。

編集 削除
魔界の仮面弁士  2004-07-07 18:16:41  No: 114585  IP: [192.*.*.*]

> 早速上記でためしてみましたが・・・
>> Set WebBrowser1.Document.f.lr(0).onclick = New Class1
> のところで実行時エラーが出てしまいました。何が足りないのでしょうか(泣)
さ、さぁ…? 何故でしょうね。(^^;)
「エラーの内容」すら書かれていないので、私には判断のしようが
ありません。
(少なくとも、こちらの環境では動作していましたよ)

もしかして、『プロシージャID』を変更するのを忘れていたとか…という事はありませんか?
あるいは、プロパティ名を間違えているとか、google以外のURLを指定していたけれど、
DocumentComplete内の処理を変更していなかったとか…。

> Set WBEvent = WebBrowser1.Documentとすることで
document全体のイベントではなく、input type="radio"のイベントを拾いましょう。

特定のコントロールを探すには、form要素のプロパティを使っても良いですし、
getElementById
getElementsByName
getElementsByTagName
などのメソッドを使う事もできます。あるいは、先のサンプルのように、
コントロール名を直接指定する方法もあります。
(過去ログにもサンプルがありますので、検索してみてください)

> WebBrowser1内のあるラジオボタンのグループに対して
> イベントを持つようなことは無理なのでしょうか?
先の私のソースで言えば、
    Set WebBrowser1.Document.f.lr(0).onclick = New Class1
    Set WebBrowser1.Document.f.lr(1).onclick = New Class1
ではなく、
    Set MyClass = New Class1
    Set WebBrowser1.Document.f.lr(0).onclick = MyClass
    Set WebBrowser1.Document.f.lr(1).onclick = MyClass
のようにするという手がありますよ。

この場合、googleページでの
  <input id=all type=radio name=lr value="" checked>
  <input id=il type=radio name=lr value=lang_ja >
という、どちらの ラジオボタン(name=lr)が押されたとしても、
同じメソッド(MyClass.MyMethod)が呼び出されますので、
イベント処理をひとまとめに出来るでしょう。

> またonclickをソースに書くとWebBrowser1内のラジオボタンに
> 色がつかなくなってしまったのですが、これは一体・・・!?
『色がつかない』という状況がわかりません。

> 選択したラジオボタンがChecked=Falseになってしまっていました。
そのラジオボタンが「選択されているかどうか」によって、
checkedプロパティの内容が変化すると思いますが…そうなりませんか?

編集 削除
HTMLって難しいんですね  2004-07-07 19:03:23  No: 114586  IP: [192.*.*.*]

ご回答ありがとうございます。
> さ、さぁ…? 何故でしょうね。(^^;)
すみません・・・問題なく動きました。すごく役に立ちそうです。
> document全体のイベントではなく、input type="radio"のイベントを拾いましょう。
これ、挑戦してみます。CLASSを利用する方が上手くいっているので
そちらで頑張ってみようと思います。

そしてラジオボタンの件ですがonclickはFunctionでTrueを返さないと
Checkedが強制的にFalseになってしまっていたみたいです。

編集 削除
HTMLって難しいんですね  2004-07-07 19:16:38  No: 114587  IP: [192.*.*.*]

おかげさまでかなり形になってきました。で、また壁が・・・。
CLASSを利用する場合、これにパラメータを渡す方法はあるのでしょうか?
ご教授いただければ幸いです。本当に次々と申し訳ないです・・・。

編集 削除
魔界の仮面弁士  2004-07-08 14:59:49  No: 114588  IP: [192.*.*.*]

> CLASSを利用する場合、
CLASSって、<p class="information"> とかで使われる、class属性の事ではなく、
先のサンプルで使った クラスモジュール の事ですよね?


> これにパラメータを渡す方法はあるのでしょうか?
パラメータというのは、例えば HTML の表記でいえば、
  <input type="radio" id="R1" name="R" onclick="MyFunc(1)">
  <input type="radio" id="R2" name="R" onclick="MyFunc(2)">
のようなイメージでしょうか?
(上記では onclickイベントにて、MyFunc関数に 1 や 2 といった引数を渡しています)

だとすればクラスよりも、UserControlのイベントの方が使いやすいかと思います。
UserControlであれば、コントロール配列にする事で、複数のイベントを束ねられますし。


'----------------------------------------
'---- ユーザーコントロール: WebEvent ----
'----------------------------------------
'InvisibleAtRuntimeプロパティは、Trueに設定してください。
'また、[DefaultMethod]プロシージャのプロシージャIDを
'必ず「既定値」に設定しておいて下さい。
'----------------------------------------
Option Explicit
Private mvarUserParameter As Variant
Public Event WebEvent(ByRef UserParameter As Variant)
Public Sub DefaultMethod()
    RaiseEvent WebEvent(mvarUserParameter)
End Sub
Public Function EventInfo(ByRef UserParameter As Variant) As WebEvent
    mvarUserParameter = UserParameter
    Set EventInfo = Me
End Function
'--以下はおまけ
Private Sub UserControl_AmbientChanged(PropertyName As String)
    Refresh
End Sub
Private Sub UserControl_Paint()
    Dim X As Single, Y As Single
    X = Screen.TwipsPerPixelX
    Y = Screen.TwipsPerPixelY
    Line (0, 0)-(ScaleWidth - X, ScaleHeight - Y), vbBlack, B
    CurrentX = X * 3
    CurrentY = Y * 3
    Print Ambient.DisplayName
End Sub

===============================================

'-----------------------------------
'---- フォームモジュール: Form1 ----
'-----------------------------------
'WebBrowser1 と WebEvent1(0) が必要です。
'
'フォームに、WebBrowserコントロールと、
'WebEventユーザーコントロールを貼っておき、
'WebEvent1のIndexプロパティを 0 にします。
'-----------------------------------
Option Explicit
Private Sub Form_Load()
    WebBrowser1.Navigate2 "http://www.google.co.jp/"
End Sub
Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    'Load WebEvent1(0)
    Load WebEvent1(1)

    'イベントへの関連付けを行います。第3引数には、任意のパラメータを渡せます。
    'ここで指定したパラメータは、WebEventイベントの引数に渡されます。
    Set WebBrowser1.Document.f.lr(0).onclick = WebEvent1(0).EventInfo("あいうえお")
    Set WebBrowser1.Document.f.lr(1).onclick = WebEvent1(1).EventInfo("かきくけこ")

    'なお、複数のパラメータを渡したい場合は、
    ' 『 Set 〜 = obj.EventInfo( Array("a", "b", "c") ) 』
    'のように、配列を使って指定してください。
End Sub
Private Sub WebEvent1_WebEvent(Index As Integer, UserParameter As Variant)
    Debug.Print "コントロール"; Index; "でイベントが発生しました。("; UserParameter; ")"
End Sub

編集 削除
魔界の仮面弁士  2004-07-08 15:03:04  No: 114589  IP: [192.*.*.*]

(誤)
>  'イベントへの関連付けを行います。第3引数には、任意のパラメータを渡せます。

(正)
'EventInfoメソッドを使って、イベントへの関連付けを行います。
'この引数には、数値や文字列など、任意のパラメータを渡す事ができます。

編集 削除
HTMLって難しいんですね  2004-07-08 18:35:09  No: 114590  IP: [192.*.*.*]

詳細なご回答、ありがとうございました。ようやく処理が実現できました。
まだまだ理解できていない部分がありますので、何度もソースを読み直し
今回ご教授いただいたものを自分の財産といたします。

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

編集 削除
HTMLって難しいんですね  2004-07-09 17:47:21  No: 114591  IP: [192.*.*.*]

またまたすみません・・・。

For Each obj In WebBrowser1.Document.getElementsByName("aaa")
    set obj.onclick = WebEvent1(x).EventInfo(xxx) 
    x = x+1
Next
という形でイベントの関連付けを試みましたが「オブジェクトがありません」とエラーになります。WebEvent1もあらかじめLoadしてあります。
このようなコントロールの指定の仕方はNGなのでしょうか。

編集 削除
魔界の仮面弁士  2004-07-09 20:31:36  No: 114592  IP: [192.*.*.*]

> 「オブジェクトがありません」とエラーになります。
まず、「どのオブジェクトが無いのか」を調べてみてください。

編集 削除
HTMLって難しいんですね  2004-07-12 09:27:42  No: 114593  IP: [192.*.*.*]

どのオブジェクトがないのかわからない・・・
Set obj = WebEvent1(x).EventInfo(xxx)
はオブジェクトがないと言われるのですが
Set WebBrowser1.Document.f.rl(xxx).onclick = WebEvent1(x).EventInfo(xxx)
この直接指定はうまくいきます。

Typenameで見るとobjもWebBrowser1.Document.f.rl(xxx).onclickも同じ
JScriptTypeInfoと出ます。同じオブジェクトをさしていることには
なっていないのでしょうか・・・。

編集 削除
HTMLって難しいんですね  2004-07-12 09:33:11  No: 114594  IP: [192.*.*.*]

きゃー!!すみません。スペルミスってました。上記のとおりでできました。ありがとうございました。

編集 削除
魔界の仮面弁士  2004-07-12 09:42:50  No: 114595  IP: [192.*.*.*]

> Set obj = WebEvent1(x).EventInfo(xxx)
> はオブジェクトがないと言われるのですが

??? 前の質問では、
「set obj.onclick = WebEvent1(x).EventInfo(xxx)」
でしたよね。どちらの構文でエラーになるのですか?


> どのオブジェクトがないのかわからない・・・
ローカル ウィンドウ や クリック ウォッチ、それに、
イミディエイト ウィンドウなどを使って、調べてみてください。

たとえば、
  Debug.Print "x="; x
  Debug.Print "WebEvent1="; TypeName(WebEvent1)
  Debug.Print "WebEvent1(x)="; TypeName(WebEvent1(x))
  Debug.Print "xxx="; xxx
  Debug.Print "WebEvent1(x).EventInfo(xxx)=";
  Debug.Print TypeName(WebEvent1(x).EventInfo(xxx))
  Debug.Print "obj="; TypeName(obj)
  Debug.Print "obj.tagName="; TypeName(obj.tagName)
  Debug.Print "obj.onclick="; TypeName(obj.onclick)
などとして、この中で エラーになる行 や Nothing な行を探してみるとか。


> 同じオブジェクトをさしていることにはなっていないのでしょうか・・・。
「Debug.Print obj1 Is obj2」が True を返すなら、obj1 と obj2 は
同じオブジェクトである、という事になります。しかし、
「Debug.Print TypeName(obj1) = TypeName(obj2)」が True を返すだけでは、
それらが同じオブジェクトである、という証拠とはなりえません。

編集 削除
HTMLって難しいんですね  2004-07-12 15:39:27  No: 114596  IP: [192.*.*.*]

魔界の仮面弁士様、丁寧なご回答ありがとうございました。
だんだん質問するのが心苦しくなる中、丁寧で分かりやすくご解説いただき
本当に救われる思いです。これからもなんとか自分で解決できるよう
全力を尽くします・・・が、困ったときはよろしくお願いいたします。

編集 削除