ダイアログの表示を検知するには?(WebBrowser)


GOMA  2004-04-06 10:34:30  No: 82863  IP: [192.*.*.*]

お世話になっております。
以前msgbox関連の質問させていただいた者です。
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200403/04030020.txt


(### 前回書いたものの抜粋(S))

開発環境:Windows2000(SP4)
開発言語:VB6.0(SP5)          
ブラウザ:IE5.5以上

今、上記の環境でブラウザ(HTML)に対する操作の記録&再生プログラムに挑戦しています。

'Webブラウザオブジェクト(イベント取得の為WithEvents)
Public WithEvents objWeb As SHDocVw.WebBrowser

'CreateObject
Set objWeb = CreateObject("InternetExplorer.Application")

とし、各イベントを拾う事で操作をスクリプトファイルとして出力し、
そのスクリプトをもとに操作を再現するというものです。

操作を記録し、再生する事は概ね成功しました。

が、ここでひとつ問題が発生したのです。
例えばINPUTエレメント(TYPE=BUTTON)の押下を再生した際、
そのボタンのonclickイベント内にmsgboxなどの処理がある場合、
そこで再生が止まってしまいます。
(そのメッセージボックスが消えない限りVBとして次のSTEPへ処理が移らない)
表示されたメッセージボックスに対しての処理自体は大体目処が立っているのですが、
VBが次のSTEPへ進めない以上、肝心のその処理の呼び出しようがない状況です。

どうにかこのmsgboxに束縛されず次のSTEPへ進める手段はないものでしょうか?
若しくはその他の回避策があれば良いのですが、、、。
又、記録対象となるWebページは不定であり、こちらでいじる事は原則出来ません。

(前回書いたものの抜粋(E) ###)



幾つかの助言を頂き、紹介していただいた海外サイト(msgboxのハンドルを監視する方法)も
参考に試行錯誤してみたのですが、やはりモーダルダイアログが表示されVBの処理が
そこで待ち状態になると、監視自体も止まってしまうようです。

前置きが少し長くなってしまいましたが、今回の質問は以下の通りです。

やはりあきらめてモーダルダイアログ(メッセージボックス含む)を監視するEXEを別に
用意する方向で考えようかと思うのですが、最後の悪あがきで質問させてください。

WebBrowserオブジェクトやDocumentオブジェクトで、ダイアログが表示された際に
発生するイベントはやはりないのでしょうか。
WebBrowserオブジェクトのNewWindow2イベントで、別ウィンドウが作成された事が検知できるのは
わかるのですが、ダイアログ関連は、ありそうでないのです・・・。

ご助言、宜しくお願い致します。

編集 削除
IMA  2004-04-06 11:35:32  No: 82864  IP: [192.*.*.*]

私の投稿の後で、GOMAさんが解決とされたので、多少修正されて動いているのかと思っていました。
前回の私の例では単にMsgBoxの表示を消すだけの動作です。
>   '取得したウインドウハンドルに終了要求のメッセージを送る
>   Form1.Text1 = Form1.Text1 & vbCrLf & "PostMessage to MsgBox ""WM_QUIT""" & vbCrLf
>   Call PostMessage(h, WM_QUIT, 0, 0)

以後の動作を継続するには、継続のためのボタンなどをクリック処理する必要があります。

MsgBoxのパターンが決まっていないはずですから、ボタンを列挙や表示テキストを判断することになると思います。    ↑これが難しそうですね!
簡単な例で、yes no 2つのボタンがあり、現在yesにフォーカスがあり、noをクリックする
と動作が継続するのであれば以下のようになると思います。

Private Sub ShowChanges(h As Long)
Dim sTypePopUp As String, sCaptionPopUp As String, sCaptionParent As String
    If FindWindowEx(h, 0, "Edit", "") Then
        sTypePopUp = "InputBox or dialog"
    Else
        sTypePopUp = "MsgBox"
    End If
    sCaptionPopUp = GetWndText(h)
    sCaptionParent = GetWndText(GetParent(h))
    If sTypePopUp = "MsgBox" And InStr(sCaptionPopUp, "hogehoge?") Then
        SendKeys "{TAB}", True
        SendKeys "{ENTER}", True
    End If
End Sub

編集 削除
GOMA  2004-04-06 13:39:11  No: 82865  IP: [192.*.*.*]

>IMAさん
今回も助言いただき、ありがとうございます。

ダイアログに対する操作自体は既にC言語で作られた別EXEがあり、
そちらで賄える目処は大体立っています。
困っているのは、ブラウザからダイアログが出たところで
その別EXEに一時バトンタッチしたいのですが、
ダイアログがでたという事をVB側で検知できない状態なのです。
VBで試作した別EXEではダイアログ検知は出来たのですが、自分自身で
検知しようとしてもダイアログが出る時点で監視も停止してしまうのです。

なので、既存のCで作られた別EXEにダイアログ監視をさせるようにしようか、
というのが今の考えなのです。
ただ、現在の構造上Cの方は改造に影響のでる個所が多い為、可能であれば
避けたいのです。
WebBrowserオブジェクトやDocumentオブジェクト等はwitheventsを用いて
使用しているので、もしダイアログポップアップ時に発生するイベントが
あれば簡単に対応できるのですが・・・。
調べたところ、それらしきものは見つからなかったのですが、
前述の通り「NewWindow2イベントがあるならダイアログも検知できそうなものなのに〜」
と思うことと、WebBrowserオブジェクトは今回初使用で経験不足な為、
実はみつかりにくいものの、そのようなイベントがあるのではないか、と、
往生際悪く検討しているところなのです。

編集 削除
IMA  2004-04-06 15:06:21  No: 82866  IP: [192.*.*.*]

お役に立てず、すいませんでした。
(まだ、どこがうまく行かないのか、よく判らないのですが・・)

  私自身、このスクリプトはVBでIEを操作してイベント,URL等を判断しながら
英文のある箇所を翻訳させる際に、その翻訳ソフトの終了時に「保存しますか?」
とのダイアログが出て、これを出た瞬間にNoを選択し前に処理を進める為に使用
しています。

つまり、翻訳ソフトの起動直前に
    SetTimer hWnd, NV_MYEVENT, 50, AddressOf TimerProc
としてタイマー監視して、以前例示したサンプルのコードを標準モジュールに
記載し、その中のShowChangesプロシージャ内に上記のようなコードを記載して
対応しています。

私のはGOMAさんの「ブラウザ(HTML)に対する操作の記録&再生プログラム」とは
少し異なりますが、複数のIEを監視し、アクティブ或いは最後にアクティブな
IEに対してイベントなどを監視し各種処理をしています。

私のプログラムで、間違った処理を行うとエラーMSGがでるURLに対してMsgBoxを
監視して、それを消したりボタンを操作することは可能で、VBで次のスクリプト
に進むことやIEの画面更新なども可能でした。

でも、GOMAさんの処理(スクリプト)では、できないのですよね?

最後に、私の知る限りにおいてはMsgBoxなどのPopUpを拾うイベントは
無いようです。

編集 削除
GOMA  2004-04-06 16:56:15  No: 82867  IP: [192.*.*.*]

>お役に立てず、すいませんでした。
とんでもないです!

VBでのmsgbox関数を使用した時と同様で、そのダイアログに対し何かしらのアクションを
起こし閉じない限り次のSTEPへ進まないのです。
又、モーダルダイアログが表示されている間はSetTimerもVB標準のタイマコントロール(こちらはダメ元で試しました)も
動作しない状態なのです。(ダイアログが消えると再び動き出します)
恐らくIMAさんとの違いは、こちらはIEをCreateObjectし、その中のHTML表示部(DocumentObject)に対し
各メソッドを実行する事で操作を再生しています。
(例)
Document.activeElement.Click  'アクティブなコントロールをクリック
この為、操作対象のボタンクリック時にScript等でダイアログを出されると、
こちら(再生プログラム(VB))と連動してしまうのではと思っています。


・・・と、ここまで書いて気付いたのですが、

>私のプログラムで、間違った処理を行うとエラーMSGがでるURLに対してMsgBoxを
>監視して、それを消したりボタンを操作することは可能で、VBで次のスクリプト
>に進むことやIEの画面更新なども可能でした。

とあるので他にも問題があるようですね。
witheventsは一時はずしてみたけれど結果は同じだったし・・・。

SetTimerの第一引数のハンドルの指定を誤ると動作しないらしいですが、
(再生プログラム自身のものを設定しています)
別のアプリケーションのダイアログは検知できたので、間違ってはいないはずです。
ううむ。

まあ最悪、目的を実現するのは前述のC言語プログラムでどうにか出来そうなのですが、
時間の許す限りあがいてみます。
(まあ、この試行錯誤がプログラミングの面白いところでもあるのですけれど)

編集 削除