• ベストアンサー

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

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

noname#208339
noname#208339

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

  • ベストアンサー
回答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オーダー順に返してくれるとは知りませんでした。 さっそく作ってみたところ、うまくいきました!! どうもありがとうございました。

関連するQ&A

  • ウィンドウのハンドルが分からない

     VC++2005ExpressEditionを使用しています.  「ファイル」->「新規作成」->「プロジェクト」->「CLR」->「Windowsフォームアプリケーション」とすると,ただの四角いフォームが作成されます.このフォームにボタンやテキストボックスを配置していくわけですが,このフォームの「ウィンドウのハンドル」を取得するのはどうすればいいのでしょうか.そもそも,このフォームに「ウィンドウのハンドル」というものは存在するのでしょうか.  呼び出したいWindowsAPI(WSAAsyncSelect)の引数の中に「ウィンドウのハンドル」というものがあって困っています.参考書のサンプルプログラムには「HWND hWnd」などと書いてあるのですが,VC++が作成したファイルの中を検索しても「HWND」という文字列はヒットしませんでした.

  • Wordでウィンドウハンドル(Hwnd)を取得したい

    Word2007、2002を使用しています。 Wordでウィンドウハンドル(Hwnd)を取得したいと思ったのですが、 どのように取得して良いかわかりませんでした。 Excelであれば以下のように取得できました。  Excel.Application.Hwnd どのようなプログラムを書けばHwndは取得できますでしょうか? 私なりに調べてみたのですが、うまく見付けられませんでした。 もしご存知でしたら、ご教示お願いいたします。

  • 親ウインドウのウインドウハンドルの必要性について

    お願いします。 WIN98 VC++6.0 SDKにて ウインドウをクリックするとダイアログボックスが表示されるサンプルプログラムがあります。 MessageBox(hWnd, s, "ダブルクリック", MB_OK);の第1引数には親ウインドウのウインドウハンドルを指定するとありましたが、NULLに変えても問題無く動きました。 第1引数はなんでも良いのでしょうか? また、必ず親ウインドウのウインドウハンドルを指定しなければならない時はどのような場合でしょうか? よろしくお願いします。

  • ハンドルのwinndowを閉じる

    WebBrowserで表示したページをマウスコントロールする処理をやっています。 ある特殊な場面で、多分WebBrwserのスクリプトでポップアップメニューが出ます(エラー発生のような)。 タイトルは空白なので GetWindow(hwnd,GW_CHILD); でその子ウンドウのハンドルを調べ、もしNULLでなかったら、子ウンドウが出たので、その中にあるcloseボタンを押すようにマウスを制御すればよいのではと考えましたが、たまにしか現れないので、そのボタンの位置を決めるのに手間がかかります。 それで、質問は、指定したハンドルを簡単に閉じる関数はないでしょうか。 また、その子ウンドウを出す部分のスクリプトがないか*.jsのソースを調べましたが、closeという文字列では見つかりませんでした(位置情報があるのではと予想)。 C++BulderXE2使用ですがmsdnの関数を想定しています。

  • OpenGLでウィンドウハンドルの取得

    コンソールアプリで作ることが前提です。 glut関数で作成したウィンドウのハンドルを取得し、その画面上に文字を表示しようとTextOutやDrawTextやらを使ってみたんですが、背景色しか表示されません。DrawTextの戻り値が18だったので成功していると思うのですが。どこがおかしいのかご指摘をお願いします。 #include<stdio.h> #include<windows.h> #include<GL/glut.h> HWND hwnd; void display(){ glClearColor(0.5,0.5,0.5,1); glClear(GL_COLOR_BUFFER_BIT); hwnd=GetActiveWindow(); PAINTSTRUCT ps; HDC hdc; RECT rect; LPCSTR str = TEXT("あああ"); GetClientRect(hwnd, &rect); hdc = BeginPaint(hwnd, &ps); SetRect( &rect, 10, 10, 100, 100); TextOut(hdc, 10, 10, str, lstrlen(str));    DrawText(hdc, TEXT("あああ"), -1, &rect,DT_CENTER); EndPaint(hwnd, &ps); glFlush(); } int main(int argc,char **argv){ glutInit(&argc,argv); glutInitWindowSize(640,480); glutCreateWindow("aaa"); glutDisplayFunc(display); glutMainLoop(); return(0); }

  • ファイルオープンの際のウィンドウハンドルの取得方法

    VC++2008にてプログラムを作成しています。 自作プログラム(疑似エクスプローラ)にて、 ShellExecute関数でファイルをオープンさせた際に、 開かれたファイルウィンドウのHWNDまたはCWndを 取得したいのですが、実現方法が分かりません。 ・やりたい事  複数ファイルをオープンさせて、各ファイルが閉じられた時に、  ファイル毎に任意の処理を行いたい。 マルチスレッドにて、CreateProcess→ファイルオープンを行い、 WaitForSingleObjectで、ファイルが閉じられるまで待機し、 コントロールが戻ってきたら、任意処理をするようにしていたのですが、 PowerPointファイルは複数ファイルを立ち上げても、 1プロセスにしかならないため、実装の変更を余儀なくされました。 CWnd->m_hWndで、各ファイルの区別が付けられるのではないかと 考え、現在、テスト用処理を組んでいるところです。 ファイルが閉じられたかどうかは、APIフックを用い、 DestroyWindowが呼ばれた際のHWNDを、自作プログラム側に送り、 ShellExecute時に取得しておいたHWND(またはCWnd)であれば、 任意処理へ移行。といった流れを考えています。 ShellExecute時に立ち上がったファイルのハンドルの 取得方法、または、全く別に、上記の目的を満たす 処理方法がありましたら、アドバイスお願いします。

  • ボタンのハンドルウィンド取得について

    OS:Windows Vista Business 開発環境:Microsoft Visual Studio C++ 2005,Microsoft Spy++ XRay(Data Analyze)----.exeを起動し、データファイルを読み込むため ボタンを押して"開く"ダイアログを表示させたいのですが、ボタンの キャプションが空白であるためハンドルウィンドが取得できません。 ボタンのコントロールIDがわかっているため、下記のようなプログラムを書いてみたのですが上手くいきません。ご教示お願いいたします。 hWnd=FindWindow("ThunderRT6FormDC",_T("XRay (Data Analyze) --- ")); SetForegroundWindow(hWnd); hbtn=GetOpenButton(hWnd); HWND GetOpenButton(HWND hdlg) {   HWND hbtn = NULL;   ::EnumChildWindows(hdlg, FindOpenButton, reinterpret_cast<LPARAM>   (&hbtn));   return hbtn; } static BOOL CALLBACK FindOpenButton(HWND hwnd,LPARAM lParam) {   TCHAR tbuf[1024];   ::GetWindowText(hwnd, tbuf, sizeof(tbuf)); //表示されているテキストを取得   if ((lstrcmp(tbuf, _T("")) == 0)&&(GetDlgCtrlID(hwnd)==0x00000032)) {     HWND *ret = reinterpret_cast<HWND*>(lParam);     *ret = hwnd;     return FALSE; //探索終了   }   return TRUE; //探索続行 } 画像は青で囲んであるのがアプリのウィンドウ、赤で囲んであるのがハンドルウィンドを取得したいボタンのウィンドウです。

  • エディタに文字を表示するためのウィンドウハンドルを取得したい

    以下のようなことをしようとしています。 ・メモ帳などのエディタが起動されている。 ・エディタは一番上のウィンドウとして存在していて、入力場所でカーソルが点滅している。 ・別プロセスからそのウィンドウにメッセージを送り、文字を表示させたい。 GetForegroundWindow()で取得したハンドルにメッセージを投げましたが何も表示されませんでした。 なので、エディタの親ウィンドウではなく、アクティブな子ウィンドウにメッセージを投げなければならないと思い、以下の処理で子ウィンドウのハンドルを取得しようと思いました。  hWndWork = GetForegroundWindow();  if(hWndWork != NULL) {   bSts = cWndWork.Attach(hWndWork);   if(bSts != 0) {    cWndTarget = cWndWork.GetActiveWindow();    if(cWndTarget != NULL) {     hWndTarget = cWndTarget->m_hWnd;    }   }  } 結果としては「hWndWork 」と「hWndTarget 」は同じでした。 考え方や、上記の処理で間違っている点などがありましたら指摘願います。 また、エディタに表示する方法をご存知であればご教授願います。

  • 【C#】FindWindowExの使い方を教えてください

    はじめまして Visual Studio 2005を使用しています。 C#.NETは、いじり初めて1週間の超初心者です。 C#.NETでのFindWindowExの使い方を教えてください。 まずはじめに、vb.netで作ったアプリAの"Form1"があり、その中にテキストボックス"TextBox1"があります。 "TextBox1"のテキスト(キャプション?)には同じく"TextBox1"と入力されています。 そこで、C#側のアプリBでVBのアプリAの"Form1"のハンドルをFindWindowで取得します。 ここまでは出来ました。 次に、FindWindowExを使って"TextBox1"のハンドルを取得したいのですが、どうしてもうまく取得できません(0が返ってきます) 以下、C#のソースです。 (textBox1のMultilineはTrueです) ================================================================== using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsApplication1 { public partial class Form1 : Form { [DllImport("user32.dll")] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] static extern IntPtr FindWindowEx(IntPtr hWnd, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); public IntPtr hWnd = (IntPtr)0; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { IntPtr hWnd; IntPtr hWndTest; string sClassName = null; string sWindowText = "AppA"; // アプリAのウインドウハンドルを取得 hWnd = FindWindow(sClassName, sWindowText); textBox1.Text = "ウインドウのハンドル " + hWnd + "\r\n"; // アプリAのウインドウ内のTextBox1のハンドルを取得 hWndTest = hWnd; sClassName = null; sWindowText = "TextBox1"; hWnd = FindWindowEx(hWndTest, IntPtr.Zero, sClassName, sWindowText); textBox1.Text += "テキストボックスのハンドル " + hWnd; } } } ================================================================== Spy++で覗くとテキストボックスにもハンドルが割り与えられているので取得できるはずだと思っているのですが、どうしてもいまくいきません。 どうか、よろしくご享受願います。 ちなみに、アプリAのテキストボックスのクラス名が”WindowsForms10.EDIT.app.0.378734a”となっているのですが、これはどの環境でビルド(コンパイル)しても不変なのでしょうか? 不変だとしたら、クラス名を使えば悩まずに取得できると思うのですが・・・(実験済み)

  • 閉じるを押してもデバッグが終了しません。

    プログラム初心者です。よろしくお願いします。 フォームアプリケーションで入門としてクリックやウィンドウの検知を行うプログラムを書いてみたのですが、右上の閉じるボタン[×]を押すとウィンドウは閉じますが、デバックは終了しません。 プロセスを見てもプロジェクト名のプロセスは残ったままで、デバッグを手動で停止させると消えます。 これはこういうものなのでしょうか? 初めて書いたプログラムなので比較対象が無くて分かりません。 以下プログラムコード project1 ------------------------------------------ (略) protected: virtual void WndProc(System::Windows::Forms::Message% m) override { switch(m.Msg) { case WM_TIMER: if(m.WParam.ToInt32()==1) { POINT point; GetCursorPos(&point); Form1::label2->Text="X:"+point.x; Form1::label3->Text="Y:"+point.y; setlocale( LC_ALL, "Japanese" ); TCHAR buff[260]; HWND hWnd; hWnd=WindowFromPoint(point); GetWindowText(hWnd, buff, sizeof(buff)); Form1::label1->Text=gcnew String(buff); }break; case WM_MOVE: Form1::label4->Text="移動しました。";break; case WM_LBUTTONDOWN: Form1::label4->Text="左クリック";break; case WM_RBUTTONDOWN: Form1::label4->Text="右クリック";break; /* default: Form1::label4->Text=m.Msg.ToString();break;*/ } Form::WndProc(m); } private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { HWND hmyWnd = static_cast<HWND>(this->Handle.ToPointer()); SetTimer(hmyWnd,1,100,NULL); } }; ------------------------------------------------------------- また、case WM_RBUTTONDOWN:の内部にClose();を書き足して実行すると 「'System.ObjectDisposedException' のハンドルされていない例外が System.Windows.Forms.dll で発生しました。」 と出ます。 何かおかしいところはありますでしょうか? それとも仕様でしょうか? お教えくださいm(_ _)m

専門家に質問してみよう