複数のドキュメント インターフェイスについて

複数ドキュメント インターフェイス (MDI) アプリケーションの各ドキュメントは、アプリケーションのメイン ウィンドウのクライアント領域内の個別の子ウィンドウに表示されます。 一般的な MDI アプリケーションには、ユーザーが複数のテキスト ドキュメントを操作できるワープロ アプリケーションや、ユーザーが複数のグラフやスプレッドシートを操作できるようにするスプレッドシート アプリケーションが含まれます。 詳細については、次の各トピックを参照してください。

フレーム、クライアント、および子ウィンドウ

MDI アプリケーションには、フレーム ウィンドウ、MDI クライアント ウィンドウ、および多数の子ウィンドウという 3 種類のウィンドウがあります。 フレーム ウィンドウは、アプリケーションのメイン ウィンドウに似ています。サイズ設定の境界線、タイトル バー、ウィンドウ メニュー、最小化ボタン、最大化ボタンがあります。 アプリケーションでは、フレーム ウィンドウのウィンドウ クラスを登録し、それをサポートするウィンドウ プロシージャを提供する必要があります。

MDI アプリケーションでは、フレーム ウィンドウのクライアント領域に出力が表示されません。 代わりに、MDI クライアント ウィンドウが表示されます。 MDI クライアント ウィンドウは、事前登録されたウィンドウ クラス MDICLIENT に属する特別な種類の子ウィンドウです。 クライアント ウィンドウはフレーム ウィンドウの子です。これは、子ウィンドウの背景として機能します。 また、子ウィンドウの作成と操作のサポートも提供します。 たとえば、MDI アプリケーションは、MDI クライアント ウィンドウにメッセージを送信することで、子ウィンドウを作成、アクティブ化、または最大化できます。

ユーザーがドキュメントを開いたり作成したりすると、クライアント ウィンドウによってドキュメントの子ウィンドウが作成されます。 クライアント ウィンドウは、アプリケーション内のすべての MDI 子ウィンドウの親ウィンドウです。 各子ウィンドウには、サイズ変更の境界線、タイトル バー、ウィンドウ メニュー、最小化ボタン、最大化ボタンがあります。 子ウィンドウはクリップされるため、クライアント ウィンドウに限定され、外部に表示することはできません。

MDI アプリケーションでは、複数の種類のドキュメントをサポートできます。 たとえば、一般的なスプレッドシート アプリケーションを使用すると、ユーザーはグラフとスプレッドシートの両方を操作できます。 MDI アプリケーションは、サポートするドキュメントの種類ごとに、子ウィンドウ クラスを登録し、そのクラスに属するウィンドウをサポートするウィンドウ プロシージャを提供する必要があります。 ウィンドウ クラスの詳細については、「 ウィンドウ クラス」を参照してください。 ウィンドウ プロシージャの詳細については、「 ウィンドウ プロシージャ」を参照してください。

一般的な MDI アプリケーションを次に示します。 Multipad という名前です。

マルチパッド mdi アプリケーション フレーム ウィンドウとクライアント ウィンドウ

子ウィンドウの作成

子ウィンドウを作成するには、MDI アプリケーションが CreateMDIWindow 関数を呼び出すか、 WM_MDICREATE メッセージを MDI クライアント ウィンドウに送信します。 MDI 子ウィンドウを作成するより効率的な方法は、 CreateWindowEx 関数を呼び出して、 拡張スタイルWS_EX_MDICHILD 指定することです。

子ウィンドウを破棄するために、MDI アプリケーションは MDI クライアント ウィンドウにWM_MDIDESTROY メッセージを送信します。

子ウィンドウのアクティブ化

任意の数の子ウィンドウを一度にクライアント ウィンドウに表示できますが、アクティブにできるのは 1 つだけです。 アクティブな子ウィンドウは、他のすべての子ウィンドウの前に配置され、その境界線が強調表示されます。

ユーザーは、非アクティブな子ウィンドウをクリックしてアクティブ化できます。 MDI アプリケーションは、 WM_MDIACTIVATE メッセージを MDI クライアント ウィンドウに送信することで、子ウィンドウをアクティブ化します。 クライアント ウィンドウはこのメッセージを処理すると、アクティブ化する子ウィンドウのウィンドウ プロシージャと非アクティブ化される子ウィンドウのウィンドウ プロシージャに WM_MDIACTIVATE メッセージを 送信します。

子ウィンドウがアクティブ化されないようにするには、FALSE を返して子ウィンドウにWM_NCACTIVATE メッセージを処理します。

システムは、重なり合うウィンドウのスタック内の各子ウィンドウの位置を追跡します。 このスタッキングは Z オーダーと呼ばれます。 ユーザーは、アクティブ ウィンドウのウィンドウ メニューから [ 次へ ] をクリックして、Z オーダーで次の子ウィンドウをアクティブ化できます。 アプリケーションは、クライアント ウィンドウに WM_MDINEXT メッセージを送信することで、Z オーダーで次の (または前の) 子ウィンドウをアクティブ化します。

アクティブな子ウィンドウへのハンドルを取得するために、MDI アプリケーションはクライアント ウィンドウ にWM_MDIGETACTIVE メッセージを送信します。

複数のドキュメント メニュー

MDI アプリケーションのフレーム ウィンドウには、ウィンドウ メニューを含むメニュー バーが含まれている必要があります。 ウィンドウ メニューには、クライアント ウィンドウ内に子ウィンドウを配置する項目、またはすべての子ウィンドウを閉じる項目が含まれている必要があります。 一般的な MDI アプリケーションのウィンドウ メニューには、次の表の項目が含まれる場合があります。

メニュー項目 目的
タイル 子ウィンドウをタイル形式で配置し、それぞれがクライアント ウィンドウ全体に表示されるようにします。
Cascade 子ウィンドウをカスケード形式で配置します。 子ウィンドウは互いに重なり合いますが、それぞれのタイトル バーが表示されます。
アイコンの整列 最小化された子ウィンドウのアイコンをクライアント ウィンドウの下部に配置します。
すべて閉じる すべての子ウィンドウを閉じます。

 

子ウィンドウが作成されるたびに、新しいメニュー項目がウィンドウ メニューに自動的に追加されます。 メニュー項目のテキストは、新しい子ウィンドウのメニュー バーのテキストと同じです。 メニュー項目をクリックすると、ユーザーは対応する子ウィンドウをアクティブ化できます。 子ウィンドウが破棄されると、対応するメニュー項目がウィンドウ メニューから自動的に削除されます。

システムは、ウィンドウ メニューに最大 10 個のメニュー項目を追加できます。 10 番目の子ウィンドウが作成されると、ウィンドウ メニューに [ その他の Windows ] 項目が追加されます。 この項目をクリックすると、[ ウィンドウの選択 ] ダイアログ ボックスが表示されます。 ダイアログ ボックスには、現在使用可能なすべての MDI 子ウィンドウのタイトルを含むリスト ボックスが含まれています。 ユーザーは、リスト ボックスのタイトルをクリックして、子ウィンドウをアクティブ化できます。

MDI アプリケーションで複数の種類の子ウィンドウがサポートされている場合は、アクティブ ウィンドウに関連付けられている操作を反映するようにメニュー バーを調整します。 これを行うには、アプリケーションがサポートする子ウィンドウの種類ごとに個別のメニュー リソースを指定します。 新しい種類の子ウィンドウがアクティブ化されると、アプリケーションはクライアント ウィンドウ にWM_MDISETMENU メッセージを送信し、対応するメニューにハンドルを渡す必要があります。

子ウィンドウが存在しない場合、メニュー バーにはドキュメントの作成または開きに使用される項目のみが含まれている必要があります。

ユーザーがカーソル キーを使用して MDI アプリケーションのメニュー内を移動する場合、キーの動作は、ユーザーが一般的なアプリケーションのメニューを移動する場合とは異なります。 MDI アプリケーションでは、コントロールはアプリケーションのウィンドウ メニューからアクティブな子ウィンドウのウィンドウ メニューに、次にメニュー バーの最初の項目に渡されます。

複数のドキュメント アクセラレータ

子ウィンドウのアクセラレータ キーを受信して処理するには、MDI アプリケーションのメッセージ ループに TranslateMDISysAccel 関数を含める必要があります。 ループは、TranslateAccelerator または DispatchMessage 関数を呼び出す前に TranslateMDISysAccel呼び出す必要があります。

MDI 子ウィンドウのウィンドウ メニューのアクセラレータ キーは、MDI 以外の子ウィンドウのキーとは異なります。 MDI 子ウィンドウでは、Alt + – (マイナス) キーの組み合わせによってウィンドウ メニューが開き、Ctrl + F4 キーの組み合わせによってアクティブな子ウィンドウが閉じられ、Ctrl + F6 キーの組み合わせによって次の子ウィンドウがアクティブになります。

子ウィンドウのサイズと配置

MDI アプリケーションは、MDI クライアント ウィンドウにメッセージを送信することで、子ウィンドウのサイズと位置を制御します。 アクティブな子ウィンドウを最大化するために、アプリケーションは WM_MDIMAXIMIZE メッセージをクライアント ウィンドウに送信します。 子ウィンドウが最大化されると、そのクライアント領域は MDI クライアント ウィンドウ全体に表示されます。 さらに、子ウィンドウのタイトル バーが自動的に非表示になり、子ウィンドウのウィンドウ メニュー アイコンと [復元] ボタンが MDI アプリケーションのメニュー バーに追加されます。 アプリケーションは、クライアント ウィンドウに WM_MDIRESTORE メッセージを送信することで、クライアント ウィンドウを元の (最大サイズの) サイズと位置に復元できます。

MDI アプリケーションは、子ウィンドウをカスケード形式またはタイル形式で配置できます。 子ウィンドウがカスケードされると、ウィンドウはスタックに表示されます。 スタックの下部にあるウィンドウは画面の左上隅を占め、残りのウィンドウは垂直方向と水平方向にオフセットされ、各子ウィンドウの左罫線とタイトル バーが表示されます。 子ウィンドウをカスケード形式で配置するために、MDI アプリケーションは WM_MDICASCADE メッセージを送信します。 通常、アプリケーションは、ユーザーがウィンドウ メニューの [カスケード ] をクリックすると、このメッセージを送信します。

子ウィンドウがタイル表示されると、各子ウィンドウが全体に表示され、ウィンドウは重複しません。 すべてのウィンドウは、必要に応じて、クライアント ウィンドウ内に収まるようにサイズ設定されます。 子ウィンドウをタイル形式で配置するために、MDI アプリケーションはクライアント ウィンドウ にWM_MDITILE メッセージを送信します。 通常、アプリケーションは、ユーザーがウィンドウ メニューの [タイル ] をクリックすると、このメッセージを送信します。

MDI アプリケーションでは、サポートされている子ウィンドウの種類ごとに異なるアイコンを提供する必要があります。 アプリケーションは、子ウィンドウ クラスを登録するときにアイコンを指定します。 子ウィンドウが最小化されると、クライアント ウィンドウの下部に子ウィンドウのアイコンが自動的に表示されます。 MDI アプリケーションは、 WM_MDIICONARRANGE メッセージを クライアント ウィンドウに送信することで、子ウィンドウアイコンを配置するようにシステムに指示します。 通常、アプリケーションは、ユーザーがウィンドウ メニューの [アイコンの配置 ] をクリックすると、このメッセージを送信します。

アイコン タイトル ウィンドウ

MDI 子ウィンドウは最小化される可能性があるため、MDI アプリケーションでは、通常の MDI 子ウィンドウのようにアイコン タイトル ウィンドウを操作しないようにする必要があります。 アプリケーションが MDI クライアント ウィンドウの子ウィンドウを列挙すると、アイコン タイトル ウィンドウが表示されます。 アイコン タイトル ウィンドウは他の子ウィンドウとは異なりますが、MDI 子ウィンドウによって所有されています。

子ウィンドウがアイコン タイトル ウィンドウであるかどうかを判断するには、GW_OWNER インデックスと共に GetWindow 関数を使用します。 タイトル以外のウィンドウは NULL を返します。 メニューとダイアログ ボックスは所有ウィンドウであるため、このテストはトップレベル ウィンドウでは不十分であることに注意してください。

子ウィンドウ データ

子ウィンドウの数はユーザーが開くドキュメントの数によって異なるため、MDI アプリケーションはデータ (現在のファイルの名前など) を各子ウィンドウに関連付けできる必要があります。 この作業を実行する 2 つの方法があります。

  • ウィンドウ構造に子ウィンドウ データを格納します。
  • ウィンドウのプロパティを使用します。

ウィンドウ構造

MDI アプリケーションがウィンドウ クラスを登録すると、この特定のウィンドウ クラスに固有のアプリケーション データ用に、ウィンドウ構造に余分な領域が予約される場合があります。 この余分な領域にデータを格納および取得するために、アプリケーションは GetWindowLong 関数と SetWindowLong 関数を 使用します。

子ウィンドウに対して大量のデータを保持するために、アプリケーションはデータ構造にメモリを割り当て、子ウィンドウに関連付けられている余分な領域に構造体を含むメモリにハンドルを格納できます。

ウィンドウ プロパティ

MDI アプリケーションでは、ウィンドウ プロパティを使用してドキュメントごとのデータを格納することもできます。 ドキュメントごとのデータ は、特定の子ウィンドウに含まれるドキュメントの種類に固有のデータです。 プロパティは、ウィンドウ クラスを登録するときに余分な領域を割り当てる必要がないという点で、ウィンドウ構造の余分な領域とは異なります。 ウィンドウには、任意の数のプロパティを含めることができます。 また、ウィンドウ構造内の余分なスペースにアクセスするためにオフセットを使用する場合、プロパティは文字列名によって参照されます。 ウィンドウのプロパティの詳細については、「 ウィンドウのプロパティ」を参照してください。