アークピットのホームページに戻る

WinAPIトピックのトップページに戻る

APIトピックの各章に移動する

ダウンロードのページに移動する
ダウンロードができ
ない場合の対処法
 

ページ移動

2-4-7. MDIクライアントウィンドウの作成

 フレームウィンドウの作成は、MDIスタイルでも、SIDのメインウィンドウを作成する手順と何ら変わりはありません。MDIらしい処理は、クライアントウィンドウを作成する手順からです。

MDIクライアントウィンドウの役割

 MDIクライアントウィンドウは、MDI機能の中核をなすウィンドウです。すべてのMDI子ウィンドウは、このクライアントウィンドウの上に表示されます。最小化のアイコンすらこの上に表示します。よって子ウィンドウの親は、このクライアントウィンドウです。子ウィンドウが少しでもクライアントウィンドウからはみ出すと、自動的にスクロールバーを表示します。しかしスクロールバーの操作性は良いとは言えません。

 MDIクライアントウィンドウは、"MDICLIENT" と言う名前のMDIシステムが用意したウィンドウクラスです。よって作成は、CreateWindow 関数で行ないます。また利用者は、このウィンドウにいろいろなメッセージを送ることにより、いろいろなサポートを得られます。例えば、MDI子ウィンドウの作成・カスケードやタイル配置・クローズ・最小化・最大化・元に戻す・アクティブの変更、そしてアイコンの配列などです。これらは、WM_MDIxxxと言う名称のメッセージです。

MDIクライアントウィンドウの作成

 フレームウィンドウのウィンドウプロシージャ(ApMdiProc)のWM_CREATEメッセージで、普通はMDIクライアントウィンドウを作成します。
        case WM_CREATE:         // メインウィンドウの新規作成
        {
            LPCREATESTRUCT     lpcs;
            CLIENTCREATESTRUCT ccs;
            HINSTANCE hInst;
            LOGFONT   lf;

            InitCommonControls();
            hRtfLib = LoadLibrary("RICHED32.DLL");
            hInst = (HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE);
            lpcs  = (LPCREATESTRUCT)lParam;
            ccs.hWindowMenu  = GetSubMenu(lpcs->hMenu,IDMC_WINDOW);
            ccs.idFirstChild = ID_MDICHILD;
            hWndClient = CreateWindow("MDICLIENT",NULL,
                                WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|
                                WS_HSCROLL|WS_VSCROLL,
                                0,0,0,0,hWnd,lpcs->hMenu,
                                hInst,(LPVOID)&ccs);
                  : (他のコード)
 クライアントウィンドウは、MDICLIENT と言う名前のMDIシステムが用意したウィンドウクラスなので、作成は、CreateWindow 関数で行ないます。この関数で、位置はすべて0ですが、これはWM_SIZEで対応するためです。メニューはフレームウィンドウのメニューを渡します。これはクライアントウィンドウ上にメニューを作成する訳ではありません。MDIのウィンドウメニュー操作するために、メニューのハンドルを管理します。普通と違うのは、lParam部分です。ここには、CLIENTCREATESTRUCT 構造体のポインタを渡します。

 CLIENTCREATESTRUCT 構造体は2つのメンバだけしかありません。最初はウィンドウメニューのポップアップのハンドルを設定します。これは前にも言いましたが、MDIでウィンドウメニューを操作するために使用します。そして2つ目のメンバは、idFirstChild で最初に作成するMDI子ウィンドウのID番号を設定します。以後作成されるごとに子ウィンドウはインクリメントした番号が自動的に付きます。これは番号で子ウィンドウを識別するのに使用しますが、あまり使われることはないでしょう。ApMdisysでもMDI子ウィンドウの種類は識別する必要があったのですが、その場合は、別の方法を取っています。

MDIクライアントウィンドウの破棄とリサイズ

 クライアントウィンドウは、WM_DESTROYで削除します。またWM_SIZEに伴って、位置とサイズを変更する必要があります。
        case WM_DESTROY:        // ウィンドウを破棄する
        {
            if (hWndClient) DestroyWindow(hWndClient);
            if (hFont) DeleteObject(hFont);
            if (hRtfLib) FreeLibrary(hRtfLib);
            break;
        }
        case WM_SIZE:           // ウィンドウのサイズが変わった
        {
            if (hWndClient)     // MDIクライアントウィンドウのサイズを調整する
                MoveWindow(hWndClient,0,0,
                          LOWORD(lParam),HIWORD(lParam),TRUE);
            return 0;
        }
 WM_DESTROYで削除します。通常は、if(hWndClient) で真偽の判定は必要ありません。これがNULLの場合は、プログラムの異常以外は、考えられないからです。

 WM_SIZEに伴って、位置とサイズを変更する必要があります。ApMdisysの場合は、クライアントウィンドウの全エリアをMDIクライアントウィンドウに割り当てます。用途によっては一部でもかまいません。

ページ移動