• 締切済み

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

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

みんなの回答

回答No.6

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

回答No.5

 こんばんは。 ・ちなみに、No.2の指摘は、EumChildWindowsの解説に ・> 子ウィンドウがさらに子ウィンドウを持つ場合、EnumChildWindows 関数はそれらのウィンドウも列挙します。 ・と書かれているので、該当しないでしょう。  ボタンコントロールも「子ウィンドウ」なので、EnumChildWindows()APIで列挙出来ます。  実際に実行しましたが、コールバックが入ってきています。  ただし、GetDlgItem()APIを利用した方が賢明であるのは事実です。

回答No.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を使用したほうが確実でしょう。

  • chie65535
  • ベストアンサー率43% (8514/19356)
回答No.3

>GetDlgIDで取得できない原因として上記の画像が示すように孫ウィンドウであるから取得できないのではないのかと考えています。 その通り。 GetDlgIDに与える「親のハンドル」は、添付画像の ウィンドウ 001003AA ThunderRT6PictureBoxDC と書かれているウィンドゥのハンドルでなければなりません。 青で囲っているアプリのウィンドゥは「親ではなく、親の親」なので、これを指定してもエラーになります(「指定のコントロールIDのコントロールは居ない」と言うエラーになる)

回答No.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;//探索続行 }

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.1

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

bug001
質問者

補足

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

関連するQ&A

  • win32 GetWindowLong

    GetWindowLongで別のプログラムのウインドウハンドルを取得してウィンドウプロシージャのアドレスを調べようと思ったのですが取得できません。他のウィンドウのウィンドウプロシージャのアドレスは取得できないのでしょうか? ------------------------------------------ #include <stdio.h> #include <string.h> #include <windows.h> struct cell{ HWND hWnd; char WindowName[256]; }; BOOL CALLBACK EnumWndProc( HWND hWnd, LPARAM lParam ) { char buff[256]=""; GetWindowText( hWnd,buff, sizeof(buff));//ウインドウの文字を取得して、 if(strcmp(buff,((cell*)lParam)->WindowName)==0){//名前が一致したら、 ((cell*)lParam)->hWnd = hWnd;//ウィンドウハンドルを渡す } return true; } int main(int argc, char* argv[]) { cell c; c.hWnd =NULL; strcpy(c.WindowName,"無題 - メモ帳");//検索するウィンドウの名前 EnumWindows( EnumWndProc, (LPARAM)&c); LONG wndproc, exstyle; if(c.hWnd != NULL){ //目的のウインドウハンドルが取得できました wndproc = GetWindowLong(c.hWnd, GWL_WNDPROC); //メモ帳のウィンドウプロシージャが取得できない exstyle = GetWindowLong(c.hWnd, GWL_EXSTYLE); } return 0; }

  •    ダイアログのクラス化で仮想関数を用いて派生クラスにしているんです

       ダイアログのクラス化で仮想関数を用いて派生クラスにしているんですが・・・ ダイアログを基本クラスで静的プロシージャと派生クラスでオーバーライドしてプロシージャを使いたい のですが、どうしても自身のポインタが取得できません。 以下にソースを載せておきます。  class CBaseWnd  {  public:    // ポインタの設定    void SetPointer( HWND hWnd );    // ウィンドウプロシージャの呼び出し    static LRESULT CALLBACK CallProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );    // ウィンドウプロシージャの実装    virtual LRESULT MainProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );  }; [クラスの実装]  //===== ポインタの設定 =====//  void CBaseWnd::SetPointer( HWND hWnd )  {    SetWindowLong( hWnd, GWL_USERDATA, (LONG)this );  }  //===== ウィンドウプロシージャの呼び出し =====//  LRESULT CALLBACK CBaseWnd::CallProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )  {    //_プロパティリストからthisポインタを取得 //ここでポインタを取得することができないでいます。値が0です。 //先にSetWindowlongをやっても値が0のままです。    CBaseWnd* thisPtr = (CBaseWnd*)GetWindowLong( hWnd, GWL_USERDATA );    //_thisポインタが取得できなかった場合...    if( ! thisPtr )    {      //_ウィンドウの作成時の場合... //ここでアクセス違反というエラーが起きる      if( message == WM_INITDIALOG )        thisPtr = (CBaseWnd*)((LPCREATESTRUCT)lParam)->lpCreateParams;      //_thisポインタが取得できた場合...      if( thisPtr )      {        //_プロパティリストにオブジェクトハンドル(thisポインタ)を設定する        thisPtr->SetPointer( hWnd );      }    }    //_thisポインタが取得できた場合...    if( thisPtr )    {      LRESULT lResult = thisPtr->MainProc( hWnd, message, wParam, lParam );      return lResult;    }    return DefWindowProc( hWnd, message, wParam, lParam );  }  //===== ウィンドウプロシージャの実装(継承可能) =====//  // ここでの記述はデフォルトの処理  //  LRESULT CBaseWnd::MainProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )  {    switch( message )    {      //_ウィンドウが破棄された場合      case WM_DESTROY:        PostQuitMessage(0);        return 0;        //_デフォルトの場合      default:        return DefWindowProc( hWnd, message, wParam, lParam );    }  } WM_INITDIALOGでダイアログの初期化中にポインタを取得しようとしますが、アクセス違反が起こり失敗します。 どなたか分かる方がいらっしゃったらご指摘お願いします。

  • なぜhButton1ボタンからのWM_COMMANDはフックできてクライアントエリアのWM_RBUTTONDOWNはフックできないのでしょうか?

    #define STRLBUTTON TEXT("マウス左ボタンが押されました from mainProc") #define STRRBUTTON TEXT("マウス右ボタンが押されました from my_HookProc") #define STRCOMMAND TEXT("ボタンが押されました") HWND hButton1; LRESULT CALLBACK my_HookProc(int nCode, WPARAM wParam, LPARAM lParam) { CWPRETSTRUCT *pcwpRetStruct = (CWPRETSTRUCT *)lParam; HDC hDC; if(nCode==HC_ACTION) { hDC = GetDC(pcwpRetStruct->hwnd); switch(pcwpRetStruct->message) { case WM_COMMAND: TextOut(hDC, 10, 10, STRCOMMAND, strlen(STRCOMMAND)); break; case WM_RBUTTONDOWN: TextOut(hDC, 10, 10, STRRBUTTON, strlen(STRRBUTTON)); break; } ReleaseDC(pcwpRetStruct->hwnd, hDC); } return CallNextHookEx(NULL, nCode, wParam, lParam); } LRESULT CALLBACK mainProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static HHOOK hHook; HDC hDC; switch(uMsg) { case WM_DESTROY: UnhookWindowsHookEx(hHook); PostQuitMessage(0); return 0; case WM_CREATE: hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, my_HookProc, NULL, GetCurrentThreadId() ); if(!hHook) MessageBox(NULL, "hooking failed", NULL, MB_OK); hButton1 = CreateWindow( "BUTTON", "hButton1", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 40, 100, 20, hWnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL ); return 0; case WM_LBUTTONDOWN: hDC = GetDC(hWnd); TextOut(hDC, 10, 10, STRLBUTTON, strlen(STRLBUTTON)); ReleaseDC(hWnd, hDC); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }

  • ウィンドウハンドルの取得方法について

    よろしくお願いします。 WIN98 VC++6.0 MFC にて 色々勉強しておりますが、今だにウィンドウハンドルの取得方法が良く分かりません。 SDKのサンプルを見ると、なるほどそうするのか。と思いますが、MFCになると分からなくなります。 たとえば、 ウィザードのデフォルトに従いダイアログベースでのプロジェクトを作成し、ボタン1と2を配置します。 以下のコードでボタン1を非表示にできます。 void CPppDlg::OnButton2() { CWnd* pButton1 = GetDlgItem (IDC_BUTTON1); pButton1->ShowWindow(SW_HIDE); } このコードにおいて、 1.SDKの BOOL ShowWindow( HWND hWnd, // handle to window int nCmdShow // show state of window ); を用いて引数が2個の形式に書きかえることは可能でしょうか? 2.可能であれば、具体的にはどう記述すれば良いのでしょうか?

  • ウィンドウアプリが思うように動かない(GetWindowTextの使い方?)

    プログラミング初心者です。Windows XP, Visual Studio 2005 PE 使用。MFCは使わない(というより使い方がわからない…)。 簡単なウィンドウプログラムを作っています。エディットボックス1つとボタン1つを含むもので、ボタンを押すとエディットボックスの文字列を取得して、もしそれが close であればプログラムを終了するようにしたいんです。 自分で書いたコードの一部(プロシージャのみ)を以下に載せます。WM_CREATE、WM_DESTROYメッセージは省略。edit1はエディットボックスのハンドル、case式の2はボタンの子ウィンドウIDです。 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ char lpString[6]; switch(msg){ case WM_COMMAND: switch(LOWORD(wParam)) { case 2: GetWindowText(edit1,lpString,6); if(lpString == "close") SendMessage(hWnd, WM_CLOSE, 0, 0); else SendMessage(edit1, WM_CLEAR, 0, 0); return 0; } return 0; default : return DefWindowProc(hWnd,msg,wParam,lParam); } return 0; } Visual Studioではちゃんとビルドしてくれるんですが、いざ実行してcloseと入力した上でボタンを押してもうんともすんとも言いません。原因は何でしょうか?素人ながらlpStringをそのまま取り出して使用してるのがまずいのではと思いますが、関数の使い方がわからず対処に困っています。教授いただければ幸いです。

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

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

  • ボタンのアイコン表示

    開発環境:Vista Visual Studio2012 C言語 CreateWindowで作成したボタンを、アイコン表示にしたいのですけれど上手くいきません。 どこが悪いのでしょうか? HWND CreatePushButton(HWND hwnd, int x, int y, int w, int h, LPCTSTR caption, int id) {     return CreateWindow(         _T("BUTTON"),         caption,         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON ;         x, y,         w, h,         hwnd,         (HMENU)(INT_PTR)id,         G_hInst,         NULL         ); } LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {    static HWND     hButton;    static HICON     m_hIcon;    switch (uMsg) {      case WM_CREATE: //ウィンドウが作られたとき         hButtonREC = CreatePushButton( hwnd,                               20, 20,                               80, 40,                                _T("テスト"),                               ID_BUTTON  );         m_hIcon = LoadIcon( NULL , IDI_ERROR );         SendDlgItemMessage( hButtonREC,                       ID_BUTTON_RCE,                       BM_SETIMAGE,                       IMAGE_ICON,                       (LPARAM)m_hIcon); }

  • 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); }

  • WM_NCLBUTTONUPについて

    タイトルバー上でのマウスボタンのアップを検出したいので、 WM_NCLBUTTONUPメッセージを拾うために、単純に以下のようなコードを書きました。 が、このコードではうまくWM_NCLBUTTONUPメッセージを拾えません。 ウィンドウを最大化しているときは問題なくメッセージを拾えるのですが、 それ以外の時(縮小表示)はメッセージを拾えません。 ただ、WM_NCLBUTTONDOWNは正しく拾うことができました。 ウィンドウが縮小表示になっている時にWM_NCLBUTTONUPを取得する場合には何か特殊な処理が必要なんでしょうか? ご存知の方がいらっしゃったら、よろしくお願いします。 // ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_NCLBUTTONUP: MessageBox(hWnd, "UP", "LBUTTON", MB_OK); return 0; case WM_DESTROY: // ウインドウが破棄されたときの処理 PostQuitMessage(0); return 0; default: // デフォルトの処理 return DefWindowProc(hWnd, message, wParam, lParam); } }

  • ちらつき防止と波形描写

    開発環境: OS : vista visual stdio c++ 2010 C言語でAPIを使っています。 録音と再生、波形表示のプログラムを作っています。 子ウィンドウを作成して、子ウィンドウにリアルタイムに波形表示を行おうと思っているのですが、上手くいきません。 画面がちらつき、再生も上手くいかなくなってしまいます。 別ウィンドウにリアルタイム波形描写する方法は、どのような方法があるのでしょうか。 現在は下記のような感じになっています。 自分が思いつく方法は、SendMessageを使うことくらいでした。 /////////////////// struct Draw  {      RECT m_recGraph , m_recGraphHalf, m_recGraph_FFT ;      HDC m_hPaint, m_hdcBMP[4];       HBITMAP m_hBMP[4] , m_hOld[4];      PAINTSTRUCT m_hPs;      HPEN m_hPenLine;   }; static LPBYTE SaveData; //録音された音データ //子ウィンドウ LRESULT CALLBACK ChildProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {   static Draw DrawS;     switch( uMsg )      {        case WM_CREATE:          描写領域のハンドルなどの収得          return 0;        case 12345: //番号は適当。とりあえずこれにする。          描写領域の裏描写          InvalidateRect( hwnd, NULL, FALSE );          return 0;        case WM_PAINT:           DrawS.m_hPaint = BeginPaint( proc.m_hWnd, &DrawS.m_hPs );           BitBlt( DrawS.m_hPaint, 150, 48, 600, 256, DrawS.m_hdcBMP[1], 0, 0, SRCCOPY);           BitBlt( DrawS.m_hPaint, 150, 350, 600, 300, DrawS.m_hdcBMP[2], 0, 0, SRCCOPY);           EndPaint(proc.m_hWnd, &DrawS.m_hPs);           return 0;       } return DefWindowProc(hwnd, uMsg, wParam, lParam); } //親ウィンドウ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {     LPBYTE DrawData; //子ウィンドウに渡すため     switch( uMsg )      {              ・              ・              ・         録音や再生の処理              ・              ・              ・       case MM_WOM_OPEN:        再生のための処理         return 0;       case MM_WOM_DONE: //再生済みバッファがここにやってくる          再生済みバッファに次のデータを入れインキュー          インキューされたデータをDrawDataにもコピー          SendMessage( 子ウィンドウハンドル, 12345. NULL, (LPSTR)DrawData );             //ここで子ウィンドウに必要なデータを送り描写させています。強引にですが・・。          return 0;      } return DefWindowProc(hwnd, uMsg, wParam, lParam); }

専門家に質問してみよう