• ベストアンサー

Zオーダーが上から2番目のウインドウのハンドル

おせわになります。 Zオーダーが上から2番目のウインドウのハンドル知る必要がありましたので、 GetWindowが使えるのではないかと思い、プログラムを作りましたがうまくいきませんでした。 次のようにしてみました。 Form1という名前の自作のフォームがメモ帳の上に重なっていたとします。 このとき、 Text1.Text = GetWindow(Form1.hwnd, GW_HWNDNEXT) こようにしてもメモ帳のハンドルが得られませんでした。 Zオーダーが上から2番目のウインドウのハンドルを知る方法を教えて頂けないでしょうか。 よろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

 解決しているかもしれませんが、サンプルを作ってみたので 回答しておきます。 >Form1という名前の自作のフォームがメモ帳の上に重なっていたとします。 >このとき、 >Text1.Text = GetWindow(Form1.hwnd, GW_HWNDNEXT)  このイメージで、ボタンを押したら自分の下のウィンドウの キャプションを表示します。(VB6.0のサンプルです。)  ウィンドウを選択する条件は、アプリによって変わってくる と思いますので、見直してください。 Private Sub Command1_Click() Dim lngReturnValue As Long Dim strWindowTextBuffer As String * 516 Dim strWindowText As String glngOwnerHwnd = GetWindow(Me.hwnd, GW_OWNER) glngPrevHwnd = 0 gblnFound = False Call EnumWindows(AddressOf EnumWindowsSubProc, 0) If glngPrevHwnd <> 0 Then lngReturnValue = GetWindowText(glngPrevHwnd, strWindowTextBuffer, Len(strWindowTextBuffer)) strWindowText = Left(strWindowTextBuffer, InStr(strWindowTextBuffer, vbNullChar) - 1) MsgBox strWindowText End If End Sub コールバックルーチンです。標準モジュールに記載してください。 Public glngOwnerHwnd As Long Public glngPrevHwnd As Long Public gblnFound As Boolean ' ' コールバック関数 - トップレベルウィンドウを列挙 ' Function EnumWindowsSubProc(ByVal hwnd As Long, ByVal lParam As Long) As Long If gblnFound = True Then If (IsWindowVisible(hwnd) = WIN32API_TRUE) And _ (GetWindowTextLength(hwnd) > 0) And _ (GetWindow(hwnd, GW_OWNER) = 0) Then glngPrevHwnd = GetLastActivePopup(hwnd) EnumWindowsSubProc = WIN32API_FALSE Else EnumWindowsSubProc = WIN32API_TRUE End If Else ' ウィンドウハンドルを保存 If glngOwnerHwnd = hwnd Then gblnFound = True End If ' 戻り値をセット EnumWindowsSubProc = WIN32API_TRUE End If End Function  APIの定義です。標準モジュールに記載してください。 ' Win32API における、True、False Public Const WIN32API_TRUE As Long = 1 Public Const WIN32API_FALSE As Long = 0 ' トップレベルウィンドウを列挙する関数 Public Declare Function EnumWindows Lib "user32" _ (ByVal lpEnumFunc As Long, _ ByVal lParam As Long) As Long ' ウィンドウのキャプションを取得する関数 Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _ (ByVal hwnd As Long, _ ByVal lpString As String, _ ByVal cch As Long) As Long ' ウィンドウのキャプションの長さを取得する関数 Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" _ (ByVal hwnd As Long) As Long ' ウィンドウが表示されているか調べる関数 Public Declare Function IsWindowVisible Lib "user32" _ (ByVal hwnd As Long) As Long ' 指定した関係のウィンドウハンドルを取得する関数 Public Declare Function GetWindow Lib "user32" _ (ByVal hwnd As Long, _ ByVal wCmd As Long) As Long Public Const GW_OWNER = 4 ' 最後にアクティブなポップアップウィンドウを調べる関数 Public Declare Function GetLastActivePopup Lib "user32" _ (ByVal hwndOwnder As Long) As Long

noname#208339
質問者

お礼

ありがとうございます。   > If (IsWindowVisible(hwnd) = WIN32API_TRUE) And _ >   (GetWindowTextLength(hwnd) > 0) And _ >   (GetWindow(hwnd, GW_OWNER) = 0) Then >   glngPrevHwnd = GetLastActivePopup(hwnd) >   EnumWindowsSubProc = WIN32API_FALSE > Else >   EnumWindowsSubProc = WIN32API_TRUE > End If 私の場合IsWindowVisible(hwnd)だけでふるい分けていたのですが、 上のようにしなければならなかったのですね。 勉強になりました。 どうもありがとうございました。

その他の回答 (2)

回答No.3

 サンプルは、タスクマネージャのタスクに表示されるものしか 対象になってなせん。一部のウィンドウは、選択されない場合が あります。  yamamoto99さんのやられたように、以下のようにvisibleだけの チェックにして、visible以外にも、キャプションの有無、最小化 されているか、ウィンドウスタイル(ツールウィンドウなどかどうか) などを、必要に応じてチェックを追加されるのがよいと思います。 If (IsWindowVisible(hwnd) = WIN32API_TRUE) Then glngPrevHwnd = hwnd EnumWindowsSubProc = WIN32API_FALSE Else EnumWindowsSubProc = WIN32API_TRUE End If

noname#208339
質問者

お礼

度重なるアドバイスどうもありがとうございます。   > キャプションの有無、最小化されているか、 > ウィンドウスタイル(ツールウィンドウなどかどうか) > などを、必要に応じてチェックを追加されるのがよいと思います。 なるほどそうですね。 最初、なぜ  GetWindow(hwnd, GW_OWNER) = 0 が必要なのか理解できずいろいろ調べていたら、VBのフォームがオーナーウインドウではないということがわかり驚きました。 ご親切にいろいろとどうもありがとうございました。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★簡単にアドバイス ・ウインドウの列挙は『EnumWindows』で行ってみましょう。 ・この関数の方が、Zオーダーを正しく探せます。というよりも  トップレベル・ウィンドウのハンドルをリストアップ出来るため  子ウインドウのハンドルはカットしてくれます。使いやすいかな。 ・列挙用のコールバック関数 EnumWindowsProc() は自作関数になります。 ・この関数でウインドウを列挙して、2つ目が列挙されたら終了すれば  ちょうど、Zオーダーの上から2番目のウインドウのハンドルを取得  できます。 ・EnumWindowsProc関数の引数 LPARAM に、ウインドウハンドルへの  ポインタを指定しておき、そこへ列挙されるウインドウハンドルを  セットしましょう。または、グローバル変数で用意したハンドルに  保存して返します。 ・あと、EnumWindowsProc で自作フォームのウインドウハンドルの次を  取得したいのならば、列挙されるハンドルと Form1.hwnd を比較して  一致したら、次に列挙されるハンドルを返す工夫が必要です。 ・以上。おわり。→私は、C/C++ なのでサンプルは紹介できません。 関連: ・http://www.winapi-database.com/Window/Change/EnumWindows.htmlhttp://www.winapi-database.com/Window/Change/EnumWindowsProc.html

参考URL:
http://www.winapi-database.com/Window/Change/
noname#208339
質問者

お礼

ありがとうございます。 > ・ウインドウの列挙は『EnumWindows』で行ってみましょう。 > ・この関数の方が、Zオーダーを正しく探せます。 そうだったんですか!! EnumWindowsは以前使ったことがあったのですが、zオーダー順に返してくれるとは知りませんでした。 さっそく作ってみたところ、うまくいきました!! どうもありがとうございました。