プロが教える店舗&オフィスのセキュリティ対策術

非常に基本的なことを質問して申し訳ございません。

●やりたいこと●
ある親ウィンドウに「テキスト」と「OKボタン」があります。
OKボタンはひとつだけです。
このOKボタンを押して、親ウィンドウを閉じるだけです。
OKボタンを押せば、親ウィンドウは勝手に閉じます。


親ウィンドウのハンドルは取得できたのですが、
子ウィンドウ(ボタン"OK")のハンドルが取得できず、
その後の処理もできておりません。

ボタンはひとつだけなので、ボタンのハンドルを検索したりしなくても、
押すことはできるような気がするのですが・・・
初心者の浅知恵で申し訳ございません。

やはり、ボタンのハンドルを取得して、押すコマンドを実行しないといけないのでしょうか?

ボタンのハンドルを取得して、押すコマンドを実行する場合、
その方法を教えていただけると幸いです。

親ウィンドウのハンドルは変数「hWindow」に入っているとして、
コードをお願いいたします。

親ウィンドウのハンドル取得に使ったFindWindow以外に宣言が必要であればご教授お願いいたします。

A 回答 (3件)

子ウィンドウを探すには、下の2つのAPIの使います。



  EnumChildWindows(hWnd,lpEnumFunc,0&)
  GetClassName(hWnd,lpClassName,nMaxCount)

EnumChildWindows が、親ウィンドウのハンドルと、子ウィンドウを受け取る関数を
与えます。ただし、子ウィンドウを受け取る関数はフォームモジュールではなく、
標準モジュールにないと駄目です。

すると与えた子ウィンドウを受け取る関数に、親ウィンドウに含まれる全ての子ウィンドウの
ハンドルが返ってきます。

返ってきたハンドルを元に GetClassName で、クラス名を取得し、ボタンのウィンドウを
特定します。今回の場合は、ボタンが1個しかないとのことなので、取得したクラス名が
Buttonであればそのハンドルがボタンのハンドルになります。
参考までに、複数個のボタンがあれば、この場合、どのボタンがOKボタンなのかを特定しない
といけません。「スパイ」とか言うソフトがあれば簡単に特定できるのですが、ない場合は、
子ウィンドウに含まれる、上記の手順で得た全てのボタンのハンドルに対して、プログラムで
BM_CLICKのメッセージを送り一つづつ確認していくしかありません。ただこの場合でも、
特性があって、親ウィンドウに複数個のボタンがあっても、子ウィンドウを受け取る関数には
必ず一定の順番にしか、ハンドルが返ってきないので、最初に一度だけ何番目のボタンかを特定
すればよいです。対象のアプリケーションを再度起動してもこの順番は変わりません。

あと、ボタンのクリックは、SendMessageで、BM_CLICK を送ればOKです。

今回は、簡単な他アプリの制御なので、そんなに問題がないですが、複雑な制御だと、
更に、ウエイトの方法だとか、制御するアプリが確実に動作しているか、確認する操作を
1ステップずつ挿入していかないと駄目です。そうすれば、全ての他のアプリケーションを
自由に操る事ができます。

本格的に作るとなると大変なので、フリーのソフトで沢山でていると思います。一度さがされたら
よいと思います。DLLタイプになっているのがよいとは思います。
以前私も使ったことがありますが、憶えていません。あしからず。現在は自作しております。
自作のがよりきめ細かく制御出来るからです。

この回答への補足

No1,2の回答者様と同じ方が回答していただいたと
勘違いしてしまいました。

深くお詫び申し上げます。

補足日時:2008/08/18 10:32
    • good
    • 0
この回答へのお礼

何度もご返答いただき誠にありがとうございます。

やはり子ウィンドウを探す必要があるのですね。
教えていただいた内容は、ほとんど理解できたので
なんとか構築できそうです。

勉強不足の稚拙な質問に対して、何度も非常に丁寧に
具体的な回答していただき誠にありがとうございます。

お礼日時:2008/08/18 10:30

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には親ウィンドウのハンドルが
ちゃんと取得されて入っております。

補足日時:2008/08/17 13:54
    • good
    • 0

# 開発環境の情報なども投稿しましょう


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とは全く関係ない、外部のアプリケーションのウインドウです。

補足日時:2008/08/17 00:58
    • good
    • 0
この回答へのお礼

誤字訂正です。
対処ではなく、対象です。

お礼日時:2008/08/17 01:22

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A