質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.33%

  • C++

    3765questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    245questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

ウィンドウの列挙

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 792

BeatStar

score 1071

C/C++ ( Windows API 実装あり ) でやっています。

ウィンドウを列挙して 指定ソフトへメッセージを送りたいのですが、

それに関しての質問があります。 ( 2つくらい。 )

質問1:

「C言語・WIN32API・C++・C#・.NET Framework」( http://www11.ocn.ne.jp/~ikalu/ )
-> 「現在表示されているウインドウを列挙する」
-> 「multimapコンテナとstringコンテナを使用したバージョン」

にあるソースコードを拝借して、multimap -> vector 等のように微妙に変えてやってみました。

ここまではいいのですが、タスクトレイっていうのですか? 「隠れているインジケーターを表示します」とある部分
に格納されている場合がありますよね?  ( 以降 tt とします )

ファイルを起動 -> tt に格納 -> ユーザが tt をクリックして ソフトを表示する

のような感じでやるソフトです。

主に常駐するようなソフトです。

これも列挙対象に入れたいのですが、どう判断すればいいのでしょうか?

一応やりたいことは、

  1. 常駐ソフト ( 音声プレイヤー etc. ) を C/C++のソフトから起動
  2. そのままでは表示されないので tt に格納されている 1 のソフト用ボタンを押した状態にする
  3. 2 で出てくるメニューから "表示" ( ソフトによって 文字列が変わると思いますが... ) を押した状態にする ( メッセージを送る )
  4. 1 のソフトが 表示される

のような感じです。

これをやるために 最低でも

  • ソフトの ウィンドウハンドル
  • tt に格納されているボタン の ID
  • tt に格納されているボタンを押したときに出てくるメニューの ID群 ( 最低でも対象は必ず )

は必要だと推測できます。

[ 上記サイトにあるソースコードを流用して作成したコード ]

// 必要なヘッダファイルはインクルード済みだとします。

// 必要なライブラリもリンク済みだとします。


//----------------------------------------------
//  構造体定義
//----------------------------------------------

struct ENUMWINDOW{
       std::string classname; // クラス名
       std::string title; // タイトルバーの文字列
       HWND        hWnd;
};





/**************************************************************
*
* クラス名: ---
*
* 関 数 名: EnumWindowsProc
*
* 目    的: ウィンドウの列挙をするためのコールバック関数
*
* 引    数:
*           HWND   hWnd := ウィンドウハンドル
*           LPARAM lp   := 引数
*
* 戻 り 値:
*           BOOL
*
* 使 用 例:
*           ---
*
* 参 ・ 引:
*           「C言語・WIN32API・C++・C#・.NET Framework」( http://www11.ocn.ne.jp/~ikalu/ )
*           ->「現在表示されているウインドウを列挙する」
*           ->「multimapコンテナとstringコンテナを使用したバージョン」
*
* 備    考:
*           ウィンドウの列挙をするEnumWindowsEx関数用。
*
**************************************************************/

BOOL CALLBACK EnumWindowsProc( HWND hWnd, LPARAM lp ){
     vector<ENUMWINDOW> *VisibleWindow = (vector<ENUMWINDOW>*)lp;

     WINDOWPLACEMENT wpm;

     wpm.length = sizeof(WINDOWPLACEMENT);

     GetWindowPlacement( hWnd, &wpm );

     if( IsWindowVisible( hWnd ) ){
          TCHAR      windowText[0x2ff];
          ENUMWINDOW ew;

          // クラス名
          GetClassName( hWnd, windowText, sizeof(windowText) );
          ew.classname = windowText;

          windowText[0] = '\0';

          // ウィンドウ
          GetWindowText( hWnd, windowText, sizeof(windowText) );
          ew.title = windowText;

          // ウィンドウハンドル
          ew.hWnd = hWnd;

          VisibleWindow->push_back( ew );
     }
return true;
}



/**************************************************************
*
* クラス名: ---
*
* 関 数 名: EnumWindowsEx
*
* 目    的: 現在 起動&表示されているウィンドウの列挙
*
* 引    数:
*           std::vector<ENUMWINDOW> &result := 結果用vector
*
* 戻 り 値:
*           int : ウィンドウの数
*
* 使 用 例:
*           int n = EnumWindowsEx( 結果用vector );
*
* 参 ・ 引:
*           「C言語・WIN32API・C++・C#・.NET Framework」( http://www11.ocn.ne.jp/~ikalu/ )
*           ->「現在表示されているウインドウを列挙する」
*           ->「multimapコンテナとstringコンテナを使用したバージョン」
*
* 備    考:
*           
*
**************************************************************/

int EnumWindowsEx( vector<ENUMWINDOW> &result ){
    EnumWindows( (WNDENUMPROC)EnumWindowsProc, (LPARAM)&result );
return result.size();
}

[ main関数内 ]

    vector<ENUMWINDOW> Window;

    cout << "Window: " << EnumWindowsEx( Window ) << endl;

    for( int i = 0; i < Window.size(); i++ ){
          cout << i << ":" << Window[i].classname << ", " << Window[i].title << " = " << Window[i].hWnd << endl;
    }

コールバック関数 EnumWindowsProc 内の IsWindowVisible関数 のブロック ( 処理自体は残して ) を排除した状態にしたところ、

列挙対象に含めない範囲まで列挙してしまいます。

私が列挙対象に含めたいのは

  • 現在表示されているウィンドウ
  • tt に格納されているウィンドウ

です。

質問2:

質問1 にあるソースコードから ウィンドウを列挙できるなら 子ウィンドウ ( コントロール ) も列挙できるのでは?

と思い、ヘルプファイルで "EnumWindows" と検索したところ、

"参照" の部分に EnumChildWindows とあったので、

Firefox を起動した状態で

[ 追加コード ]

struct ENUMCHILDWINDOW{
       HWND parent; // 親ウィンドウハンドル
       HWND hWnd; // コントロールのウィンドウハンドル
       int  ControlID; // コントロールID
};


BOOL CALLBACK EnumWindowsProc( HWND hWnd, LPARAM lp ){
     vector<ENUMCHILDWINDOW> *v = (vector<ENUMCHILDWINDOW>*)lp;

          ENUMCHILDWINDOW ew;

          ew.hWnd = hWnd;

          ew.ControlID = GetWindowLong( hWnd, GWL_ID );

          v->push_back( ew );
return true;
}


int EnumChildWindowsEx( HWND hWnd, vector<ENUMCHILDWINDOW> &result ){
    EnumChildProc( hWnd, (WNDENUMPROC)EnumWindowsProc, (LPARAM)&result );
return result.size();
}

と書いて、

vector<ENUMCHILDWINDOW> firefox;

for( int i = 0; i < Window.size(); i++ ){
      if( Window[i].title.find( "Firefox" ) != string::npos ){
           EnumChildWindowsEx( Window[i].hWnd, firefox );
      }
}

for( int i = 0; i < firefox.size(); i++ ){
      cout << "HWND: " << firefox[i].hWnd << " ID: " << firefox[i].ControlID << endl;
}

を追加して、チェックしてみたところ、

何も表示されませんでした。

ウィンドウの指定を適当にして ( i = 3 とか ) チェックしたところ、

ContorlID の桁が かなり多い感じのものがありました。

これって出来ているのでしょうか?

私がやるときは 基本的に IDは コントロールの場合 102から開始しますが、コントロール数が少ないせいもあり、

110かそこらまでしか使いません。

ですが、ウィンドウの指定を適当... の部分で表示したものは 231341 みたいに 桁がかなり多くて...

[環境等]
言語: C/C++ ( Windows API あり )
コンパイラ: MinGW

宜しくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

具体的な回答は置いといて…

この手の要求を満たそうと思うとSPY++を使わないと
デバッグが辛いと思うので
もし、存在を知らない or 使ったことが無い
であれば是非どうぞ

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

現在表示されているウィンドウ

今のままでよいと思います。

tt に格納されているウィンドウ

Shell Tray Info - Arrange your system tray icons - CodeProject あたりが参考になりそうです。
トレイアイコン押下時に表示されるウィンドウは必ずしも表示状態にあるわけではないはず。
アイコン押下時にそのイベントを取得して表示状態にするなどの処理になるため、トレイアイコンに紐づく情報を取得することで、ウィンドウにたどり着くことができるかどうかを調べてください。

これって出来ているのでしょうか?

「数字が大きいからできていない」という判断がわかりません。
取れている = できている ですよね!?
Window ID は確か int 型なので、その範囲内だったら仕様として正しいかと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C++

    3765questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    245questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。