初めて質問いたします。
現在VisualBasic6.0(SP5)とWIN32APIを使って
「他アプリケーション(市販されたプログラム)の操作」をするプログラムを
作っています。
やりたい処理は「コマンドボタンをクリックしたときに表示されるダイアログ
から目的のキャプションがついたボタン(「はい」「いいえ」など)を探し出す」
(その後に探し出したボタンをクリックする)ものなのですが、ボタンクリック
で出てきたダイアログからボタンを即座に探し出すことができません。
(ダイアログを既に開いた状態で同処理を行うとボタン検索ができます。
アプリケーションのフォームとダイアログのタイトルは両方とも同じです)
アプリケーションのクラスとダイアログのクラス(#32770)を使って
ウィンドウハンドルを導くことはできるのですが、APIを本格的に
使うのは初めてなので解決法をうまく導くことができません(T-T)
解決策に繋がるものをご教授願えれば幸いです。
---------(やりたい処理のソース(API定義は割愛))
Public Function MsgPic(ByVal strWName As String, ByVal strBName As String) As Boolean
Dim WINDOW_NAME As String '* フォーム・ダイアログのキャプション
Dim BUTTON_NAME As String '* ボタンのキャプション
Dim hWnd As Long
Dim hChild As Long
Dim i As Long
Dim lRet As Long
MsgPic = False
WINDOW_NAME = strWName
BUTTON_NAME = strBName
'フォームのハンドルを取る
hWnd = FindWindow(vbNullString, WINDOW_NAME)
If hWnd = 0 Then
Exit Function
End If
'ダイアログのハンドルを取る
hChild = FindWindowEx(hWnd, 0, "#32770", WINDOW_NAME)
If hChild = 0 Then
Exit Function
End If
'ウィンドウ内の部品名をリストに列記
frmMain.List1.Clear
lRet = EnumChildWindows(hChild, AddressOf EnumChildProc, 0)
'リストから目的ボタンのキャプションを探す
For i = 0 To frmMain.List1.ListCount - 1
’目標ボタンのキャプションと一致するか
If InStr(1, frmMain.List1.List(i), BUTTON_NAME) > 0 Then
MsgPic = True
Exit Function
End If
Next i
End Function
Public Function EnumChildProc(ByVal hWnd As Long, lParam As Long) As Long
Dim Ret As Long
Dim Leng As Long
Dim Name As String
'バッファ確保
Name = String(255, Chr(0))
Leng = Len(Name)
'名前を取得する
Ret = GetWindowText(hWnd, Name, Leng)
'* 子ウィンドウがなくなるまで繰り返す
If Ret <> 0 Then
frmMain.List1.AddItem Name
End If
EnumChildProc = 1
End Function
>即座に探し出すことができません
という原因は
'フォームのハンドルを取る
hWnd = FindWindow(vbNullString, WINDOW_NAME)
If hWnd = 0 Then
Exit Function
End If
'ダイアログのハンドルを取る
hChild = FindWindowEx(hWnd, 0, "#32770", WINDOW_NAME)
If hChild = 0 Then
Exit Function
End If
のいずれかでウィンドウハンドルを取得するのに失敗しているからですか?
確認してみてください。
>3−t様
昨日上げたソースに「どこまで処理が進むか」チェックしてみたところ、
'ダイアログのハンドルを取る
hChild = FindWindowEx(hWnd, 0, "#32770", WINDOW_NAME)
If hChild = 0 Then
Exit Function
End If
の所でこけてしまう(ハンドル取得に失敗する)ようです。
コマンドボタン(ダイアログを出すもの)のクリック後に
sleepを入れたりdoeventsをいれてダイアログを認識させようと
試みたのですが、うまくいきません。
アプリケーションのフォームに配置されているコマンドボタン
ならうまく取れるのですが・・・。
'ダイアログのハンドルを取る
hChild = FindWindowEx(hWnd, 0, "#32770", WINDOW_NAME)
If hChild = 0 Then
Exit Function
End If
でハンドルが取得できない原因は何ですか?
ダイアログが表示されていないからですか?
確認してみてください。
>3−t様
>ハンドルが取得できない原因は何ですか?
ダイアログが表示されていないからですか?
(別関数にて)他アプリケーションのクリックするコマンドボタンが
持っているハンドルを取得しSendMessageでボタンクリックさせると
ダイアログが表示されるのですが、そのダイアログのハンドルを
取得する為にアプリケーションのハンドル(FindWindow)
→ダイアログのハンドル(FindWindowEx)と追って探そうとすると
FindwindowExの結果=0で処理から抜けてしまうようです。
(アプリケーションとダイアログにはウィンドウの親子関係はない?)
例:市販アプリケーションの「ファイル出力」ボタンをクリックさせると
『この内容でファイル出力を行いますか?(はい)(いいえ)』という
内容のダイアログが表示される。
この表示されたダイアログにある(はい)ボタンを探し出したい。
((はい)ボタンを見つけた場合、別関数でボタンクリックを実行する)
ちなみにVB側のソースでは他アプリケーションをAppActivateで
アクティブにしてからクリック処理などを行っています。
ダイアログが表示されている状態で実行すれば取得できるのであれば
考えられるのはFindWindowExを実行するタイミングの問題と思ったわけですが
ステップ実行して、ダイアログが表示されるのを確認してから処理を実行しても同じ結果ですか?
>3−t様
>ダイアログが表示されている状態で実行すれば取得できるのであれば
>考えられるのはFindWindowExを実行するタイミングの問題と思ったわけですが
>ステップ実行して、ダイアログが表示されるのを確認してから処理を実行しても同じ結果ですか?
ステップ処理で順追って処理を進めるとボタンクリック用関数の
ラスト(BM_CLICKをSendMessageしてダイアログを表示されたところ)
で止まってしまい、ダイアログの検索までたどり着きませんでした。
表示されたダイアログのボタンをEnterキーなどを使って手動でクリック
するとダイアログは消えますが、ダイアログを消した後にダイアログの
検索が実行されました。(手動クリック後にクリック関数を抜ける)
ちなみにクリック用の関数ソースは以下のとおりです。
-----------
Public Sub BtnPush(ByVal strWCls As String, ByVal strWName As String, ByVal strBCls As String, ByVal strBName As String)
Dim WINDOW_CLS As String '* フォームのクラス
Dim WINDOW_NAME As String '* フォームのキャプション
Dim BUTTON_CLS As String '* ボタンのクラス
Dim BUTTON_NAME As String '* ボタンのキャプション
Dim hWnd As Long
Dim hChild As Long
Dim sWndText As String
Dim lRet As Long
WINDOW_CLS = strWCls
WINDOW_NAME = strWName
BUTTON_CLS = strBCls
BUTTON_NAME = strBName
'大元のハンドルを取る
hWnd = FindWindow(WINDOW_CLS, WINDOW_NAME)
If hWnd = 0 Then
Exit Sub
End If
'ボタンのハンドルを取る
hChild = FindWindowEx(hWnd, 0, BUTTON_CLS, BUTTON_NAME)
If hChild = 0 Then
Exit Sub
End If
SendMessage hChild, WM_ACTIVATE, 1, 0&
SendMessage hChild, BM_CLICK, 0, 0&
End Sub
クリック関数の呼び出し例(ファイル出力ボタンをクリックさせる場合)
Call BtnPush("TSearchCondition", "SearchCondition", "TButton", "ファイル出力")
-------
SendMessage→PostMessageにしても止まってしまいますか?
>3−t様
>SendMessage→PostMessageにしても止まってしまいますか?
ボタンクリック用関数のSendMessageをPostMessageに替えて
ステップ処理させたところ、BM_CLICKした後の処理に向かう
(ボタンクリック処理が終了する)ようになりました。
PostMessageを使った方法で試してみようと思います。
t−3様 多数のアドバイスありがとうございました。<(_ _)>
ツイート | ![]() |