MDI frame_windowのsize変更後にMSGが届かない

このQ&Aのポイント
  • Windowsプログラミングにおいて、MDIのフレームウィンドウのサイズを変更すると、ダブルクリックのメッセージが届かなくなる問題についての質問です。
  • フレームウィンドウのサイズを変更してしまうと、クライアントウィンドウのダブルクリックによるMDI子ウィンドウの生成ができなくなります。
  • ダブルクリックのメッセージが届かなくなる理由について詳しくご教示いただきたいです。
回答を見る
  • ベストアンサー

MDI frame_windowのsize変更後にMSGが届かない

C++のカテゴリでWindowsプログラミングの質問もおかしいと思いましたが、他に質問するカテゴリが無かったので申し訳ありませんが、よろしくお願いします。 久しぶりに時間が空いたため、windows apiを使って自作でクラスライブラリを作成に挑戦し、WINDOWSプログラミングを行っています。 MDIウィンドウのアプリケーションについて質問です。 アプリケーション起動時に、MDIのフレームウィンドウとクライアントウィンドウを生成し、クライアントウィンドウをダブルクリックした時に、MDI子ウィンドウを生成するようにプログラムを作成しました。 アプリケーション起動後、フレームウィンドウのサイズを変更せずにクライアントウィンドウ領域でダブルクリックするとダブルクリックした回数分、MDI子ウィンドウが生成されました。 しかし、一度でもフレームウィンドウのサイズを変更してしまった場合に、ダブルクリックしてもMDI子ウィンドウが生成されなくなってしまいました。 (※「WM_LBUTTONDBLCLK」メッセージ自体が来なくなった。) 何故、ダブルクリックのメッセージが来なくなるのか心当たりが無く困っています。 以下のホームページにクライアントウィンドウのリサイズした時の処理について記載されていますが、内容を追加しても解決しませんでした。 http://www.arcpit.co.jp/winapi/api_02/ap020407.htm 申し訳ありませんが、ダブルクリックのメッセージが来なくなる理由についてお心当たりがあれば、お教えお願い致します。 ※環境 OS:Windows Vista Home Basic 開発環境:Visual C++ Express Edition

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

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

 こんばんは。  何となく想像がつくのですが、MDIフレーム側のプロシージャでWM_LBUTTONDBLCLKメッセージを処理しているのではないでしょうか。  メッセージが来なくなったのは、リサイズされた時にMDIクライアントがサイズ調整されてMDIフレームのクライアント領域に覆いかぶさった為だと思います。  MDIフレーム→MDIクライアント→MDIチャイルド(複数)と言う構成になるので、MDIクライアント側のプロシージャ側で処理すれば出来るのではないでしょうか。  上記URLで言えば、  hWndClient = CreateWindow("MDICLIENT", NULL, ...)  で作成しているhWndClientのプロシージャ内でWM_LBUTTONDBLCLKメッセージを処理すると言う事です。  また、MDIクライアントはシステム側に登録されているウィンドウですので、プロシージャをフックする必要があります。  実行していないのですが、以下のような感じでしょうか。 static WNDPROC _S_wndProcMDIClientOrg = NULL; LRESULT CALLBACK WndProcMDIClient(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_LBUTTONDBLCLK: { //此処でMDIチャイルドを作成する break; } } return ::CallWindowProc(_S_wndProcMDIClientOrg, hWnd, uMsg, wParam, lParam); } //MDIフレーム側 LRESULT CALLBACK WndProcMDIFrame(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_CREATE: { LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam; CLIENTCREATESTRUCT ccs; ccs.hWindowMenu = GetSubMenu(lpcs->hMenu,IDMC_WINDOW); ccs.idFirstChild = ID_MDICHILD; RECT crc = {0}; ::GetClientRect(hWnd, &rc); //MDIクライアントの作成 HINSTANCE hInst = (HINSTANCE)::GetWindowLong(hWnd, GWL_HINSTANCE); HWND hWndClient = ::CreateWindowEx(0, "MDICLIENT",NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_HSCROLL | WS_VSCROLL, 0, 0, rc.right, rc.bottom, hWnd, lpcs->hMenu, hInst, (LPVOID)&ccs); const DWORD dwClsStyle = ::GetClassLong(hWndClient, GCL_STYLE); ::SetClassLong(hWndClient, GCL_STYLE, dwClsStyle | CS_DBLCLKS); //MDIクライアントのプロシージャフック _S_wndProcMDIClientOrg = (WNDPROC)::SetWindowLong(hWndClient, GWL_WNDPROC, (LONG)&::WndProcMDIClient); } } //... }

hiro_knigh
質問者

お礼

回答ありがとうございます。 [machongola]様の回答で問題解決しました。 私の勘違いは以下の通りでした。 (1)MDIクライアントウィンドウに対してはMDIフレームウィンドウの  ウィンドウプロシージャが適用されていると勘違いしていた所。 回答を参照し以下の不足点を補い、問題解決しました。 (1)MDIクライアントのウィンドウスタイルでダブルクリックメッセージも  受け付けるように対応 (2)MDIクライアントウィンドウのデフォルトウィンドウプロシージャの  アドレスをフックし、ダブルクリックメッセージは新規ウィンドウ  プロシージャで対応、それ以外はフックしたウィンドウプロシージャで  対応 今までWINDOWS系OSでプログラムを組んできましたが、組込み系のソフトで、独自に用意されているクラスライブラリを使用してのプログラム開発ばかりでしたので、勉強になりました。 これで、独自のクラスライブラリを作って遊んでみようと頑張ってみている夢を続けられます。 質問自体が少ない情報で申し訳ありませんでした。 本当にありがとうございます。

関連するQ&A

  • MDIプログラムで子ウィンドウの相対座標を得るには?

    VC++6.0でMDIプログラムを作っています。 Viewクラスでマウスの右ダブルクリックのメッセージを受け取って、 その関数の中で毎回、アクティブな子ウィンドウの左上の相対座標、 つまり、クライアント領域での子ウィンドウの左上の座標を知りたいのですが、 どのようにすれば得られるか分かりません。分かる方教えてください。

  • フレームのデフォルトのサイズについて

    また気になることが出てきましたので、よろしくお願いします。 VC++6.0 MFC MDIにて フレーム(親ウィンドウ)のサイズは、MainFrm.cpp内の以下にて変更することができますが、変更しないときは、デフォルトのサイズのウィンドウが生成されます。 そのデフォルトのサイズは、rectDefaultで定義されてるらしいということまでは調べたのですが、具体的にはどこでどのように定義されているのでしょうか? ご存知の方、よろしくお願いします。 ************************** BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CMDIFrameWnd::PreCreateWindow(cs) ) return FALSE; // TODO: この位置で CREATESTRUCT cs を修正して、Window クラスやスタイルを // 修正してください。 return TRUE; }

  • MDIでのダイアログ生成

    VC++2005でMDIアプリケーションを作成しています。 ダイアログベースでは、DoModal()にてダイアログを生成していましたが、 MDIでのダイアログ生成の方法が分かりません。。 調べた結果、 (1)CreateWindow()にてクライアントウィンドウを作成 (2)CreateMDIWindow()にて子ウィンドウを作成 の順序で処理を行うことは分かりましたが、 関数の一部の引数に何を設定してやれば良いのかが不明です。。 ※下記はネット上にあったサンプルソースです。  「???」の箇所が不明な引数です。 (1) CreateWindow(   TEXT("MDICLIENT"), //MDICLIENT は固定です   NULL,   WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,   0, 0, 0, 0,   hWnd,       //メインウィンドウのハンドル←???   (HMENU)1,    //←???   hInst,       //インスタンスハンドル←???   (LPSTR)&ccs    //CLIENTCREATESTRUCT構造体のポインタ←???  ); (2) HWND CreateMDIWindow(  MDI_CHILD ,   //ウィンドウクラス名  TITLE ,     //ウィンドウのタイトルバーテキスト  0 ,       //ウィンドウスタイル。WS_MAXIMIZE(最大化表示)など  CW_USEDEFAULT , //X座標  CW_USEDEFAULT , //Y座標  CW_USEDEFAULT , //幅  CW_USEDEFAULT , //高さ  hClientWindow , //クライアントウィンドウのハンドル ←???  hIns ,      //インスタンスハンドル       ←???  0        //アプリケーション定義の値 ); なお、行いたい処理の流れとしては、 CTestDialogクラスより、CTest2Dialogクラスのダイアログを、 呼び出したいのです。 うまく説明できず申し訳ありませんが、 お詳しい方おられましたら、具体例など交えてご説明頂けると幸いです。 お手数ですが、どうか宜しくお願い致します。

  • タイトルバーのダブルクリックによるサイズ変更防止

    タイトルバーの上をダブルクリックすると、ウインドウのサイズが変更されますが、これを防止するにはレジストリをどのように変更すればよいのでしょうか? また、左上のアプリケーションアイコンもクリックすると右クリックメニューが出てしまいますが、これを防止する方法はないのでしょうか? よろしくお願いします。

  • MDI起動時に空のウィンドウが開かないようにするには?

    初歩的な質問で恐縮なのですが、 MDIアプリケーションで起動時に空のウィンドウが開かないようにするにはどうすればよいのでしょうか? 目的 MDIで作ったデータ入力ソフトがありまして、それを閲覧専用に改造したいのです。 つまり、既存のファイルを開くだけでいいのに最初に空ファイルのウインドウが立ち上がるのがウザイということです。 もとのプロジェクトはVC++5.0で作られており(作成者がいなくなってしまった)、今はVC++6.0にコンバートして編集しています。

  • DLしたExcelファイルがMDIウィンドウになる

    こんにちは。阿部です。 ExcelファイルをダウンロードするWebアプリを作っているのですが、ダウンロードしたExcelファイルを開くとMDIウィンドウの状態になり困っています。 作成するExcelファイルが問題なのか、ダウンロード時に指定するContent-Typeが問題なのかわかりませんが、Excelのウィンドウいっぱいにシートを表示したいのですが可能でしょうか? 環境 クライアント Excel 2010 Windows 7 サーバ IIS7/Windows 2008R2 テストで、ExcelファイルをWebサーバにおいて、ローカルのExcelファイルを開いて、その後、サーバのExcelファイルを指定するとMDIウィンドウになり、ダウンロードしたExcelが小さなウィンドウで開いてしまいます。 できれば、MDIウィンドウにはならず、ウィンドウいっぱいにシートが開いてほしい。

  • ウィンドウの最大化サイズを変更する方法はありませんか。

    ウィンドウの最大化サイズを変更する方法はありませんか。 Windowsのタイトルバーをダブルクリックするとそのウィンドウは画面一杯のサイズになりますが、これを自分の希望したサイズになるようにすることはできないでしょうか。

  • javaでスライダーからフレームのサイズを変更する

    プログラミング初心者です。 GUIプログラミングの勉強をしています。 質問の内容ですが、一つのウィンドウ内で 縦スライダーによるRGB値の変更とその反映 横スライダーによるウィンドウフレームサイズの変更 できるプログラムを書いています。 そこで分らない点が出てきたので、質問させていただきました。 題名の通りなのですが、 「横スライダーによるウィンドウフレームサイズの変更」の方法がわかりません。 コードを書きたいのですが文字制限があるので 一部抜粋で書き込ませていただきます。 回答お願いできますでしょうか。 以下コードです。 (ここより上はRGBのラベル作成やテキストフィールドの貼り付けなどです) String[] label2={"Height","Width"}; JTextField[] txf2 =new JTextField[2]; Border line2 = new LineBorder( Color.red, 2 ); for(i=0;i<2;i++){ txf2[i] =new JTextField("100",2); title1 =new TitledBorder(line,label[i]); txf[i].setBorder( title1 ); txf[i].setEditable(false); } panel=new JPanel[4]; for(i=0;i<4;i++) panel[i]=new JPanel(); panel[1].add(txf[3]); slide=new JSlider[3]; rgb=new int[3]; for(i=0;i<3;i++){ rgb[3]=slide[i].getValue(); panel[0].add(slide[i]); } pane.add(panel[0],BorderLayout.NORTH); panel[4].setBackground(new Color(rgb[0],rgb[1],rgb[2])); pane.add(panel[4],BorderLayout.CENTER); slide=new JSlider[2]; size=new int[2]; for(i=0;i<2;i++){ size[2]=slide[i].getValue(); panel[3].add(slide[i]); } pane.add(panel[3],BorderLayout.WEST); Slider.setSize( size[0],size[1]); 以上です。 ウィンドウのサイズ変更を取得するのに >Slider.setSize( size[0],size[1]); この配列から数値をとっているのでここが悪いのはわかっているんですが、 何をどう書き換えれば、サイズ変更がうまく反映されるのか全くわかりません。 大変長くなった上、下手な文章ですが、ご回答よろしくお願いします。

  • VC++6.0,MDI,子ウィンドウのタイトルが変わる!?

    VC++6.0でMDIプログラムを作成しているものです. 子ウィンドウをダブルクリックすると「ファイルを開く」のコモンダイアログを呼び出し,そこに選択した画像ファイルを表示させるプログラムを作ったのですが,ついでにタイトルバーに開いたファイル名を以下のようにして表示させました. // Viewクラスにて CFileDialog dlg(TRUE, "bmp", "*.bmp",               OFN_HIDEREADONLY|         OFN_OVERWRITEPROMPT,        "BITMAP(*.bmp)|         *.bmp|JPEG(*.jpg)|         *.jpg||"); if (dlg.DoModal() != IDOK) { return; } GetParent()->SetWindowText(dlg.GetFileName()); そして,画像を表示したウィンドウとは別のウィンドウをアクティブにすると,タイトルバーに表示したファイル名がウィンドウを生成したときのタイトルに戻ってしまいます. 子ウィンドウが何個あっても,表示している画像のファイル名をタイトルバーに表示したいのですが,どうすればいいのですか?

  • MDIフォームのメニュー構成

    開発言語: VB.net 開発環境: VisualStudio2005 .NET FrameWork: 2.0 現在、VB.netにてクライアント/サーバ形式のシステムの構築を行っているのですがメニュー画面の構築でお客様から以下の要望があがりました。 1. 画面左側にツリービューのメニューを表示し、右側に実画面を配置する。 2. ツリービューのメニューをクリックすると該当機能が起動すること(機能の切り替えがツリービューから行えること)。 3. メインのウインドウとしては1枚で行うこと。 WEBでのフレームを切った画面構成やVisualStudioの[ツール]-[オプション]画面のような構成をイメージされているようです。 クライアント/サーバシステムではご要望の形式は難しいとは思うのですが実現できるかどうかの評価を行っています。 現在、自分が考えている構想は以下の通りです。 ・MDIフォームを使用する ・MDI親フォーム左側にツリービューコントロールを配置する。 ・ツリービューから機能をクリックされた場合、子フォームとして表示する。 実際にテストしてみたのですが、ツリービューコントロールを配置し、クリックによって子フォームを開くところまでは成功しました。 しかし、表示したフォームがツリビューコントロールの下にもぐってしまいます。表示位置の指定もできましたが最大化されると同じことが 発生すると思います。こういう場合は親フォームにメニューバーを使用するしか手はないのでしょうか? 個人的には非常に複雑になるので要望の取り下げ依頼も必要かなと思っているのですがクライアント/サーバ形式でこういう機能を実現された方いらっしゃいましたらお教えください。 まったく別の方法で実現された方の意見等もお聞かせいただけるとありがたいです。 以上、宜しくお願い致します。