- ベストアンサー
親ウインドウにあるOKボタンを押す方法
非常に基本的なことを質問して申し訳ございません。 ●やりたいこと● ある親ウィンドウに「テキスト」と「OKボタン」があります。 OKボタンはひとつだけです。 このOKボタンを押して、親ウィンドウを閉じるだけです。 OKボタンを押せば、親ウィンドウは勝手に閉じます。 親ウィンドウのハンドルは取得できたのですが、 子ウィンドウ(ボタン"OK")のハンドルが取得できず、 その後の処理もできておりません。 ボタンはひとつだけなので、ボタンのハンドルを検索したりしなくても、 押すことはできるような気がするのですが・・・ 初心者の浅知恵で申し訳ございません。 やはり、ボタンのハンドルを取得して、押すコマンドを実行しないといけないのでしょうか? ボタンのハンドルを取得して、押すコマンドを実行する場合、 その方法を教えていただけると幸いです。 親ウィンドウのハンドルは変数「hWindow」に入っているとして、 コードをお願いいたします。 親ウィンドウのハンドル取得に使ったFindWindow以外に宣言が必要であればご教授お願いいたします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
子ウィンドウを探すには、下の2つのAPIの使います。 EnumChildWindows(hWnd,lpEnumFunc,0&) GetClassName(hWnd,lpClassName,nMaxCount) EnumChildWindows が、親ウィンドウのハンドルと、子ウィンドウを受け取る関数を 与えます。ただし、子ウィンドウを受け取る関数はフォームモジュールではなく、 標準モジュールにないと駄目です。 すると与えた子ウィンドウを受け取る関数に、親ウィンドウに含まれる全ての子ウィンドウの ハンドルが返ってきます。 返ってきたハンドルを元に GetClassName で、クラス名を取得し、ボタンのウィンドウを 特定します。今回の場合は、ボタンが1個しかないとのことなので、取得したクラス名が Buttonであればそのハンドルがボタンのハンドルになります。 参考までに、複数個のボタンがあれば、この場合、どのボタンがOKボタンなのかを特定しない といけません。「スパイ」とか言うソフトがあれば簡単に特定できるのですが、ない場合は、 子ウィンドウに含まれる、上記の手順で得た全てのボタンのハンドルに対して、プログラムで BM_CLICKのメッセージを送り一つづつ確認していくしかありません。ただこの場合でも、 特性があって、親ウィンドウに複数個のボタンがあっても、子ウィンドウを受け取る関数には 必ず一定の順番にしか、ハンドルが返ってきないので、最初に一度だけ何番目のボタンかを特定 すればよいです。対象のアプリケーションを再度起動してもこの順番は変わりません。 あと、ボタンのクリックは、SendMessageで、BM_CLICK を送ればOKです。 今回は、簡単な他アプリの制御なので、そんなに問題がないですが、複雑な制御だと、 更に、ウエイトの方法だとか、制御するアプリが確実に動作しているか、確認する操作を 1ステップずつ挿入していかないと駄目です。そうすれば、全ての他のアプリケーションを 自由に操る事ができます。 本格的に作るとなると大変なので、フリーのソフトで沢山でていると思います。一度さがされたら よいと思います。DLLタイプになっているのがよいとは思います。 以前私も使ったことがありますが、憶えていません。あしからず。現在は自作しております。 自作のがよりきめ細かく制御出来るからです。
その他の回答 (2)
- redfox63
- ベストアンサー率71% (1325/1856)
FindWindowでは子コントロールは探せないので GetWindowとGetWidnowText、GetClassNameなどを組み合わせて ボタンのハンドルを特定しないといけないでしょう hBtn = GetWindow( hWindow, GW_CHILD ) sText = String( 255, vbNullChar ) GetWindowText hBtn, sText, len( sText ) sClass = String( 255, vbNullChar ) GetClassName hBtn, sClass, len(sClass) といった具合で sTextがOK、sClassにBUTTONが含まれるなどの条件を満たす物を探すことになりそうです クリックイベントを送信するには SendMessage ボタンのリソースIDの取得にはGetDlgCtrlID を使います Declare Function SendMessage Lib "User32" ( ByVal hWnd as Long, ByVal wParam as Long, ByVal lParam as long) as Long Declare Function GetDlgCtrlID Lib "User32" ( byVal hWnd as long) as long といった宣言をしておいて nID = GetDlgCtrlID( hBtn ) SendMessage hWindow, WM_COMMAND, BN_CLICKED * &H10000 + nID, hBtn といった具合に クリックメッセージを送るといった具合になるともいます
補足
ありがとうございます。 教えていただいた内容を、試行錯誤しております。 たびたび申し訳ございません、 子ウィンドウのハンドルの取得についてですが、 hBtn = FindWindowEx(hwindow, 0, "Button", "OK") これでは取得できないのでしょうか? エラーの0しか帰ってきません。hwindowには親ウィンドウのハンドルが ちゃんと取得されて入っております。
- redfox63
- ベストアンサー率71% (1325/1856)
# 開発環境の情報なども投稿しましょう VBのバージョンは何でしょう? VB6以前、VB.NET系列 VB6以前なら そのOKボタンのイベントハンドラのアクセス指定子をPrivateからPublicに変更して Form1.OK_Clickといった具合でいいと思います VB2005以降なら VB6同様にPrivateからPublicに変更して MyオブジェクトのFormsコレクションからForm1などのOK_Clickメソッドを適切な引数で呼び出しましょう VB.NET2002/2003の場合、閉じるフォーム側に閉じられるフォームのオブジェクト変数が必要になるでしょう ボタンクリックのアクセス指定子の変更は他の場合同様に行います Form1が閉じられる側、Form2が閉じる側なら Form2側に Form1型の変数またはプロパティを用意します Public oForm as Form1 Form1からForm2を開く際に Dim frm as new Form2 frm.oForm = me frm.Show といった具合にします Form2側からForm1を閉じるイベントで oForm.OK_Click( oForm.OK, new EventArgs() ) といった具合でしょう
お礼
誤字訂正です。 対処ではなく、対象です。
補足
大変申し訳ございません。 開発環境は、ExcelVBAです。Excelは2003です。 OKをクリックする対処のウィンドウは VBとは全く関係ない、外部のアプリケーションのウインドウです。
お礼
何度もご返答いただき誠にありがとうございます。 やはり子ウィンドウを探す必要があるのですね。 教えていただいた内容は、ほとんど理解できたので なんとか構築できそうです。 勉強不足の稚拙な質問に対して、何度も非常に丁寧に 具体的な回答していただき誠にありがとうございます。
補足
No1,2の回答者様と同じ方が回答していただいたと 勘違いしてしまいました。 深くお詫び申し上げます。