- 締切済み
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クラスのダイアログを、 呼び出したいのです。 うまく説明できず申し訳ありませんが、 お詳しい方おられましたら、具体例など交えてご説明頂けると幸いです。 お手数ですが、どうか宜しくお願い致します。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- chie65536(@chie65535)
- ベストアンサー率44% (8800/19958)
追記と訂正。 フレームウインドウの中のクライアント領域に「クライアントウィンドウ」を作成し、そのクライアントウィンドウの中に、子MDIウィンドウを作成する必要があります。 先ほどの回答では「クライアントウィンドウの作成」を失念していました。 フレームウインドウ(WinMainで作る) クライアントウィンドウ(プロシジャコールバックのWM_CREATEで作る) 最初に作られる子MDIウィンドウ1 WM_MDICREATEなどで後から作られる子MDIウィンドウ2 WM_MDICREATEなどで後から作られる子MDIウィンドウ3 という関係になります。 http://wisdom.sakura.ne.jp/system/winapi/win32/win139.html を参考にすると良いでしょう。 なお、クライアントウインドウを作る時の「(HMENU)1」の「1」は、フレームウィンドウ内に作るウィンドウのID番号で、 LRESULT CALLBACK FrameProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) { (中略) switch (msg) { (中略) case WM_COMMAND: if (LOWORD(wp) == 1) { //CreateWindowのhMenu引数の値。この「1」が「(HMENU)1」に対応する 何かの処理 } (以下略) って感じで使います。 なお、紹介したページにも書いてますが、ウインドウプロシージャのコールバック関数から呼ぶ「デフォルトプロシージャ」が普通と違うので注意して下さい。 また「クライアントウィンドウのクラス名」は、システムに登録済みの「TEXT("MDICLIENT")」でなければなりません。 同様に「子MDIウインドウのクラス名」も、システムに登録済みの「TEXT("MDICHILD")」でなければなりません。 これらは「ボタンのクラス名はTEXT("BUTTON")にしなければならない」のと同じです。
- chie65536(@chie65535)
- ベストアンサー率44% (8800/19958)
メインウィンドウの作成 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hWnd; WNDCLASSEX wndclass ; wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_??????; //好みのスタイルで wndclass.lpfnWndProc = WndProc; //メッセージ処理のコールバック関数 wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; //WinMainの第1引数 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); //アイコン wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); //カーソル wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //ブラシ wndclass.lpszMenuName = NULL; //メニュー wndclass.lpszClassName = TEXT("MDICLIENT"); //クラス名 wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION); RegisterClassEx (&wndclass); // ウインドウクラスMDICLIENTを登録 hWnd = CreateWindow( //hWndが「親ウィンドウのハンドル」。★1 TEXT("MDICLIENT"), //クラス名 TEXT("子ウィンドウを作るMDIのテスト"), //タイトルバー WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, 0, 0, //表示位置 256, 256, //ウィンドウサイズ NULL, //親ウィンドウのハンドルだが親は居ない NULL, //メニューはない hInstance, //WinMainの第1引数 NULL //CLIENTCREATESTRUCT構造体のポインタ ); 以下略。 子MDIウィンドウの作成 HWND hChildWnd; hChildWnd = CreateMDIWindow( MDI_CHILD , //ウィンドウクラス名 TITLE , //ウィンドウのタイトルバーテキスト 0 , //ウィンドウスタイル。WS_MAXIMIZE(最大化表示)など CW_USEDEFAULT , //X座標 CW_USEDEFAULT , //Y座標 CW_USEDEFAULT , //幅 CW_USEDEFAULT , //高さ hWnd , //親ウィンドウのハンドル。上記★1で返されたハンドル hInstance, //WinMainの第1引数 0 //アプリケーション定義の値 );
補足
こちらが予測していた以上に具体的な回答ありがとうございます! コメントも丁寧に記載して頂き、非常に分かりやすいです。 インスタンスハンドル「hInstance」について、 WinMain関数の引数でもらっているのですね。 私が作成したいプログラムでは、ボタン押下のタイミングで、 子MDIウィンドウを作成したいので、インスタンスハンドルをグローバルか、 クラスのメンバ変数に持たせて、それをボタンハンドラ関数内で 使用してやるという方法を思いつきました。 もしその方法が不可能であったり、この方が効率が良いなどありましたら、 お手数ですが、再度ご指摘頂けませんでしょうか? 【参考URL】 http://www.kab-studio.biz/Programing/Codian/MxA/03.html
お礼
これ以上深く質問してしまうと、掲題の主旨に沿わないので、 申し訳ありませんが、いったんここで締め切らせて頂きます。 上記疑問点については、現時点で未解決なので、 また改めて質問させて頂きます。 chie65535様、ご丁寧な解説ありがとうございました。 大変参考になりました。よろしければまたご教授宜しくお願い致します。
補足
chie65535様、追加のご回答ありがとうございます。 どうやらMDIで作成する場合、複雑な手順を踏まないといけないようですね。。 とりあえず、WinMain関数を作成しようと思い、 CTestDialogクラス内に、下記の雛形を追加しました。 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow){ MSG msg; while ( GetMessage( &msg, NULL, 0, 0 ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } return msg.wParam; } ビルドしてみると、通るのですが、 中にデバッグポイントを打って実行してみても、 どうやら中に入っていないようです。 WinMain関数が正しく動いていれば、プログラム実行時に 自動で呼び出される認識なのですが。。 何か定義が間違っているのでしょうか?? 重ねての質問申し訳ありませんが、ご回答頂けると幸いです。