こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

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

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; //探索続行
}
画像は青で囲んであるのがアプリのウィンドウ、赤で囲んであるのがハンドルウィンドを取得したいボタンのウィンドウです。

投稿日時 - 2009-09-08 14:10:19

QNo.5272735

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.6

僕が書いたNo.4の回答内容は、EnumChildWindowsがボタンコントロールを列挙できることを前提に、列挙されたウィンドウと求めたいボタンコントロールが同一であるとする判定方法が間違っていないか確かめるためのデバッグ方法です。
EnumChildWindowsの仕様から、孫ウィンドウ以下を自ら列挙しに行く必要はないのですが、たとえそうロジックを変更したとしても、判定条件を間違っていたのでは目的を達することはできないと思います。

投稿日時 - 2009-09-12 20:14:08

ANo.5

 こんばんは。

・ちなみに、No.2の指摘は、EumChildWindowsの解説に
・> 子ウィンドウがさらに子ウィンドウを持つ場合、EnumChildWindows 関数はそれらのウィンドウも列挙します。
・と書かれているので、該当しないでしょう。

 ボタンコントロールも「子ウィンドウ」なので、EnumChildWindows()APIで列挙出来ます。
 実際に実行しましたが、コールバックが入ってきています。
 ただし、GetDlgItem()APIを利用した方が賢明であるのは事実です。

投稿日時 - 2009-09-12 19:33:15

ANo.4

なぜうまくいかないかを調べたいのであれば、Spy++で対象のボタンのHWNDを調べた上で、FindOpenButton関数の最初に

if (hWnd==0x001003ca)
hwnd = hwnd;

のように調べたHWNDと一致するか判断する行を追加し、その次の行にブレークポイントを設定して実行します。ブレークがかからなければ、親ウィンドウとして渡しているhdlgが正しくない可能性があります。
ブレークがかかったら、GetWindowTextとGetDlgCtrlIDが何を返しているかを調べれば、if文に与えている条件が正しいか確認できます。lstrcmpが空の文字列を比較できない可能性を排除するために、lstrlen(tbuf)==0に条件を置き換えてみる必要があるかもしれません。

ちなみに、No.2の指摘は、EumChildWindowsの解説に

> 子ウィンドウがさらに子ウィンドウを持つ場合、EnumChildWindows 関数はそれらのウィンドウも列挙します。

と書かれているので、該当しないでしょう。

なお、コントロールIDは親ウィンドウが違えば同じ値を使用できるので、ウィンドウキャプションが空でコントロールIDが0x00000032のウィンドウが複数存在する可能性があります。ボタンの親ウィンドウを別の方法で取得した上で、GetDlgItemを使用したほうが確実でしょう。

投稿日時 - 2009-09-12 15:47:40

ANo.3

>GetDlgIDで取得できない原因として上記の画像が示すように孫ウィンドウであるから取得できないのではないのかと考えています。

その通り。

GetDlgIDに与える「親のハンドル」は、添付画像の
ウィンドウ 001003AA ThunderRT6PictureBoxDC
と書かれているウィンドゥのハンドルでなければなりません。

青で囲っているアプリのウィンドゥは「親ではなく、親の親」なので、これを指定してもエラーになります(「指定のコントロールIDのコントロールは居ない」と言うエラーになる)

投稿日時 - 2009-09-10 16:24:15

ANo.2

 こんにちは。
 子ウィンドウから更に子ウィンドウへ下っていかないといけないのではないでしょうか。
 実行していないのですが、以下のような感じでも無理でしょうか。

static BOOL CALLBACK FindOpenButton(HWND hwnd,LPARAM lParam)
{
HWND *ret = reinterpret_cast<HWND*>(lParam);
TCHAR tbuf[1024];
::GetWindowText(hwnd, tbuf, sizeof(tbuf)); //表示されているテキストを取得
if((lstrcmp(tbuf, _T("")) == 0)&&(GetDlgCtrlID(hwnd)==0x00000032))
{
*ret = hwnd;
return FALSE; //探索終了
}

//更に子ウィンドウを探す(下に子ウィンドウが存在しない事もある為、戻り値は使用出来ない)
::EnumChildWindows(hwnd, FindOpenButton, lParam);
return *ret == NULL ? TRUE : FALSE;//探索続行
}

投稿日時 - 2009-09-10 11:11:07

ANo.1

対象の子ウィンドウを持っている親ウィンドウのハンドルが
既にあって、コントロールの識別子が分かっているなら、
GetDlgItemを使用すればウィンドウハンドルを取得できると思いますが。。。

投稿日時 - 2009-09-09 05:15:37

補足

>対象の子ウィンドウを持っている親ウィンドウのハンドルが
>既にあって、コントロールの識別子が分かっているなら、
>GetDlgItemを使用すればウィンドウハンドルを取得できると思います
>が。。。
そうおもってGetDlgItemで親ウィンドウのハンドルと押下する対象のボタンのコントロールID(0x00000032)を使ってやってみたのですが、
戻り値が0000000でボタンのウィンドウハンドルが取得できていないようだったので他の方法で取得できないものかと考え、すべてのウィンドウハンドルを列挙する方法をさがしているのです。
GetDlgIDで取得できない原因として上記の画像が示すように孫ウィンドウであるから取得できないのではないのかと考えています。

投稿日時 - 2009-09-09 09:12:20