次の方法で共有


ウィンドウ機能

この概要では、ウィンドウの種類、状態、サイズ、位置などのウィンドウの機能について説明します。

ウィンドウの種類

このセクションには、ウィンドウの種類について説明する次のトピックが含まれています。

重なり合ったウィンドウ

重なり合うウィンドウは、タイトル バー、罫線、クライアント領域を持つ最上位ウィンドウ (子ウィンドウ以外) です。これは、アプリケーションのメイン ウィンドウとして機能することを目的とします。 また、ウィンドウ メニュー、最小化ボタンと最大化ボタン、スクロール バーを含めることもできます。 メイン ウィンドウとして使用される重なり合ったウィンドウには、通常、これらのコンポーネントがすべて含まれます。

CreateWindowEx 関数でWS_OVERLAPPEDまたはWS_OVERLAPPEDWINDOWスタイルを指定すると、アプリケーションによって重複するウィンドウが作成されます。 WS_OVERLAPPED スタイルを使用する場合、ウィンドウにはタイトル バーと罫線があります。 WS_OVERLAPPEDWINDOW スタイルを使用する場合、ウィンドウにはタイトル バー、サイズ変更罫線、ウィンドウ メニュー、最小化ボタンと最大化ボタンがあります。

ポップアップ ウィンドウ

ポップアップ ウィンドウは、アプリケーションのメイン ウィンドウの外部に表示されるダイアログ ボックス、メッセージ ボックス、およびその他の一時的なウィンドウに使用される特殊な種類の重複ウィンドウです。 タイトル バーは、ポップアップ ウィンドウでは省略可能です。それ以外の場合、ポップアップ ウィンドウは 、WS_OVERLAPPED スタイルの重なり合ったウィンドウと同じです。

ポップアップ ウィンドウを作成するには、CreateWindowExWS_POPUP スタイルを指定します。 タイトル バーを含めるには、 WS_CAPTION スタイルを指定します。 WS_POPUPWINDOW スタイルを使用して、境界線とウィンドウ メニューを含むポップアップ ウィンドウを作成します。 ウィンドウ メニューを表示するには、WS_CAPTION スタイルをWS_POPUPWINDOW スタイルと組み合わせる必要があります。

子ウィンドウ

子ウィンドウにはWS_CHILDスタイルがあり、親ウィンドウのクライアント領域に限定されます。 通常、アプリケーションは子ウィンドウを使用して、親ウィンドウのクライアント領域を機能領域に分割します。 子ウィンドウを作成するには、CreateWindowEx 関数でWS_CHILD スタイルを指定します。

子ウィンドウには親ウィンドウが必要です。 親ウィンドウには、重なり合ったウィンドウ、ポップアップ ウィンドウ、または別の子ウィンドウを指定できます。 CreateWindowEx を呼び出すときに親ウィンドウを指定します。 CreateWindowExWS_CHILD スタイルを指定しても親ウィンドウを指定しない場合、ウィンドウは作成されません。

子ウィンドウにはクライアント領域がありますが、明示的に要求されない限り、他の機能はありません。 アプリケーションでは、タイトル バー、ウィンドウ メニュー、最小化と最大化ボタン、境界線、およびスクロール バーを子ウィンドウに要求できますが、子ウィンドウにはメニューを含めることはできません。 アプリケーションでメニュー ハンドルが指定されている場合は、子ウィンドウ クラスを登録するとき、または子ウィンドウを作成するときに、メニュー ハンドルは無視されます。 罫線のスタイルが指定されていない場合は、罫線のないウィンドウが作成されます。 アプリケーションでは、境界なしの子ウィンドウを使用して、親ウィンドウのクライアント領域を分割しながら、ユーザーに対して分割を非表示にすることができます。

このセクションでは、子ウィンドウの次の側面について説明します。

位置付け

システムは常に、親ウィンドウのクライアント領域の左上隅を基準にして子ウィンドウを配置します。 子ウィンドウの一部が親ウィンドウの境界線の外側に表示されることはありません。 アプリケーションが親ウィンドウより大きい子ウィンドウを作成するか、子ウィンドウの一部または全部が親の境界線を超えるように子ウィンドウを配置する場合、システムは子ウィンドウをクリップします。つまり、親ウィンドウのクライアント領域の外側の部分は表示されません。 親ウィンドウに影響を与えるアクションは、次のように子ウィンドウにも影響を与える可能性があります。

親ウィンドウ 子ウィンドウ
Destroyed 親ウィンドウが破棄される前に破棄されます。
[非表示] 親ウィンドウを非表示にする前に非表示にします。 子ウィンドウは、親ウィンドウが表示されている場合にのみ表示されます。
移動済み 親ウィンドウのクライアント領域と共に移動しました。 子ウィンドウは、移動後にクライアント領域を描画する役割を担います。
表示 親ウィンドウが表示された後に表示されます。

 

クリッピング

システムは、親ウィンドウのクライアント領域から子ウィンドウを自動的にクリップしません。 つまり、親ウィンドウが子ウィンドウと同じ場所に描画を実行すると、子ウィンドウの上に描画されます。 ただし、親ウィンドウに WS_CLIPCHILDREN スタイルがある場合、親ウィンドウのクライアント領域から子ウィンドウがクリップされます。 子ウィンドウがクリップされている場合、親ウィンドウはその上に描画できません。

子ウィンドウは、同じクライアント領域内の他の子ウィンドウと重なることがあります。 1 つ以上の他の子ウィンドウと同じ親ウィンドウを共有する子ウィンドウは、 兄弟ウィンドウと呼ばれます。 兄弟ウィンドウは、子ウィンドウの 1 つに WS_CLIPSIBLINGS スタイルがない限り、互いのクライアント領域に描画できます。 子ウィンドウにこのスタイルがある場合、子ウィンドウ内にある兄弟ウィンドウの任意の部分がクリップされます。

ウィンドウに WS_CLIPCHILDREN または WS_CLIPSIBLINGS スタイルがある場合は、パフォーマンスが若干低下します。 各ウィンドウはシステム リソースを占有するため、アプリケーションでは子ウィンドウを無差別に使用しないでください。 最適なパフォーマンスを得るには、メイン ウィンドウを論理的に分割する必要があるアプリケーションは、子ウィンドウを使用するのではなく、メイン ウィンドウのウィンドウ プロシージャで行う必要があります。

親ウィンドウとの関係

アプリケーションは 、SetParent 関数を呼び出すことによって、既存の子ウィンドウの親ウィンドウを変更できます。 この場合、システムは古い親ウィンドウのクライアント領域から子ウィンドウを削除し、新しい親ウィンドウのクライアント領域に移動します。 SetParentNULL ハンドルが指定されている場合、デスクトップ ウィンドウは新しい親ウィンドウになります。 この場合、子ウィンドウはデスクトップ上に描画され、他のウィンドウの境界線の外側に描画されます。 GetParent 関数は、子ウィンドウの親ウィンドウへのハンドルを取得します。

親ウィンドウは、クライアント領域の一部を子ウィンドウに放棄し、子ウィンドウはこの領域からすべての入力を受け取ります。 ウィンドウ クラスは、親ウィンドウの子ウィンドウごとに同じである必要はありません。 つまり、アプリケーションは、異なる外観の子ウィンドウで親ウィンドウに入力し、さまざまなタスクを実行できます。 たとえば、ダイアログ ボックスにはさまざまな種類のコントロールを含めることができます。各コントロールには、ユーザーのさまざまな種類のデータを受け入れる子ウィンドウがあります。

子ウィンドウには親ウィンドウが 1 つだけありますが、親ウィンドウには任意の数の子ウィンドウを含めることができます。 各子ウィンドウには、子ウィンドウを含めることができます。 このウィンドウチェーンでは、各子ウィンドウは元の親ウィンドウの子孫ウィンドウと呼ばれます。 アプリケーションは IsChild 関数を使用して、特定のウィンドウが子ウィンドウか、特定の親ウィンドウの子孫ウィンドウかを検出します。

EnumChildWindows 関数は、親ウィンドウの子ウィンドウを列挙します。 次 に、EnumChildWindows は 、各子ウィンドウにハンドルをアプリケーション定義のコールバック関数に渡します。 指定された親ウィンドウの子孫ウィンドウも列挙されます。

メッセージ

システムは、子ウィンドウの入力メッセージを子ウィンドウに直接渡します。メッセージは親ウィンドウを介して渡されません。 唯一の例外は、子ウィンドウが EnableWindow 関数によって無効になっている場合です。 この場合、子ウィンドウに移動した入力メッセージは、代わりに親ウィンドウに渡されます。 これにより、親ウィンドウで入力メッセージを調べ、必要に応じて子ウィンドウを有効にすることができます。

子ウィンドウには、一意の整数識別子を指定できます。 コントロール ウィンドウを操作する場合は、子ウィンドウ識別子が重要です。 アプリケーションは、メッセージを送信することによってコントロールのアクティビティを指示します。 アプリケーションは、コントロールの子ウィンドウ識別子を使用して、メッセージをコントロールに転送します。 さらに、コントロールは親ウィンドウに通知メッセージを送信します。 通知メッセージには、コントロールの子ウィンドウ識別子が含まれます。この識別子は、親がメッセージを送信したコントロールを識別するために使用します。 アプリケーションは、CreateWindowEx 関数の hMenu パラメーターをメニュー ハンドルではなく値に設定することで、他の種類の子ウィンドウの子ウィンドウ識別子を指定します。

レイヤード ウィンドウ

レイヤー ウィンドウを使用すると、複雑な図形を持つウィンドウ、図形をアニメーション化するウィンドウ、またはアルファ ブレンド効果を使用したいウィンドウのパフォーマンスと視覚効果を大幅に向上させることができます。 システムは、階層化されたウィンドウと基になるアプリケーションのウィンドウを自動的に作成および再描画します。 その結果、複雑なウィンドウ領域の一般的なちらつきなしで、レイヤー化されたウィンドウがスムーズにレンダリングされます。 さらに、レイヤードウィンドウは部分的に半透明、つまりアルファブレンドすることができます。

レイヤー ウィンドウを作成するには、CreateWindowEx 関数を呼び出すときに拡張ウィンドウ スタイルWS_EX_LAYERED指定するか、または SetWindowLong 関数を呼び出して、ウィンドウの作成後にWS_EX_LAYEREDを設定します。 CreateWindowEx 呼び出しの後、このウィンドウに対して SetLayeredWindowAttributes または UpdateLayeredWindow 関数が呼び出されるまで、レイヤーウィンドウは表示されません。

注意

Windows 8 以降では、子ウィンドウと最上位ウィンドウでWS_EX_LAYEREDを使用できます。 以前のバージョンの Windows では、最上位のウィンドウに対してのみ WS_EX_LAYERED がサポートされています。

 

特定のレイヤー化されたウィンドウの不透明度レベルまたは透明度の色キーを設定するには、 SetLayeredWindowAttributes を呼び出します。 呼び出し後も、ウィンドウが表示またはサイズ変更されたときに、システムによってウィンドウに描画が求められる場合があります。 ただし、システムは階層化されたウィンドウのイメージを格納するため、デスクトップ上で相対的なウィンドウの移動の結果としてウィンドウの一部が表示された場合、ウィンドウに描画を求めるメッセージは表示されません。 システムは SetLayeredWindowAttributes と呼ばれるウィンドウの描画を画面外のメモリにリダイレクトし、目的の効果を実現するために再計算するため、レガシ アプリケーションは、ウィンドウの半透明または透過性の効果を追加する場合に、描画コードを再構築する必要はありません。

アニメーションをより高速かつ効率的に行う場合、またはピクセル単位のアルファが必要な場合は、 UpdateLayeredWindow を呼び出します。 UpdateLayeredWindow は、主に、システムが SetLayeredWindowAttributes を介して提供するリダイレクト メカニズムを使用せずに、階層化されたウィンドウの図形とコンテンツを直接提供する必要がある場合に使用する必要があります。 さらに、 UpdateLayeredWindow を使用すると、リダイレクトされたウィンドウのイメージを格納するために必要な追加のメモリがシステムに必要ないため、メモリをより効率的に直接使用できます。 ウィンドウのアニメーション化の効率を最大限に高めるために、 UpdateLayeredWindow を呼び出して、階層化されたウィンドウの位置とサイズを変更します。 SetLayeredWindowAttributes が呼び出された後、レイヤー スタイル ビットがクリアされて再び設定されるまで、後続の UpdateLayeredWindow 呼び出しは失敗することに注意してください。

レイヤーウィンドウのヒット テストは、ウィンドウの形状と透明度に基づいています。 つまり、カラー キーが設定されているウィンドウ、またはアルファ値が 0 のウィンドウの領域では、マウス メッセージが通過します。 ただし、レイヤーウィンドウに WS_EX_TRANSPARENT 拡張ウィンドウスタイルがある場合、レイヤーウィンドウの形状は無視され、マウスイベントはレイヤーウィンドウの下の他のウィンドウに渡されます。

Message-Only Windows

メッセージのみのウィンドウを使用すると、メッセージを送受信できます。 表示されず、z オーダーがなく、列挙できず、ブロードキャスト メッセージを受信しません。 ウィンドウは単にメッセージをディスパッチします。

メッセージ専用ウィンドウを作成するには、CreateWindowEx 関数の hWndParent パラメーターで、HWND_MESSAGE定数または既存のメッセージ専用ウィンドウへのハンドルを指定します。 SetParent 関数の hWndNewParent パラメーターで HWND_MESSAGEを指定することで、既存のウィンドウをメッセージ専用ウィンドウに変更することもできます。

メッセージのみのウィンドウを検索するには、FindWindowEx 関数の hwndParent パラメーターでHWND_MESSAGEを指定します。 さらに、 FindWindowEx は、 hwndParent パラメーターと hwndChildAfter パラメーターの両方が NULL の場合に、メッセージのみのウィンドウと最上位ウィンドウを検索します。

ウィンドウのリレーションシップ

ウィンドウをユーザーまたは別のウィンドウに関連付けるには、さまざまな方法があります。 ウィンドウには、所有ウィンドウ、前景ウィンドウ、または背景ウィンドウがあります。 ウィンドウには、他のウィンドウに対する z オーダーも含まれます。 詳細については、次のトピックを参照してください。

前景ウィンドウと背景ウィンドウ

各プロセスには複数の実行スレッドを含め、各スレッドはウィンドウを作成できます。 ユーザーが現在作業しているウィンドウを作成したスレッドはフォアグラウンド スレッドと呼ばれ、ウィンドウは フォアグラウンド ウィンドウと呼ばれます。 他のすべてのスレッドはバックグラウンド スレッドであり、バックグラウンド スレッドによって作成されたウィンドウは バックグラウンド ウィンドウと呼ばれます。

各スレッドには、スレッドが受け取る CPU 時間の量を決定する優先順位レベルがあります。 アプリケーションではスレッドの優先度レベルを設定できますが、通常、フォアグラウンド スレッドの優先度レベルはバックグラウンド スレッドよりも若干高くなります。 優先度が高いため、フォアグラウンド スレッドはバックグラウンド スレッドよりも多くの CPU 時間を受け取ります。 フォアグラウンド スレッドの通常の基本優先度は 9 です。バックグラウンド スレッドの通常の基本優先度は 7 です。

ユーザーは、ウィンドウをクリックするか、Alt + Tab キーまたは Alt + ESC キーの組み合わせを使用して、前景ウィンドウを設定します。 フォアグラウンド ウィンドウへのハンドルを取得するには、 GetForegroundWindow 関数を 使用します。 アプリケーション ウィンドウがフォアグラウンド ウィンドウであるかどうかをチェックするには、GetForegroundWindow によって返されるハンドルをアプリケーション ウィンドウのハンドルと比較します。

アプリケーションは 、SetForegroundWindow 関数を使用してフォアグラウンド ウィンドウを設定します。

フォアグラウンド ウィンドウを設定できるプロセスが制限されます。 プロセスでは、次の場合にのみフォアグラウンド ウィンドウを設定できます。

  • 次の条件はすべて当てはまります。
    • SetForegroundWindow を呼び出すプロセスは、Windows 8または 8.1 用に設計された UWP アプリや Windows ストア アプリではなく、デスクトップ アプリケーションに属します。
    • 前景プロセスでは、 LockSetForegroundWindow 関数の以前の呼び出しによって SetForegroundWindow の呼び出しが無効にされていません。
    • フォアグラウンド ロックタイムアウトの有効期限が切れています (「SystemParametersInfoSPI_GETFOREGROUNDLOCKTIMEOUT」を参照してください)。
    • アクティブなメニューはありません。
  • さらに、次の条件の少なくとも 1 つが当てはまります。
    • 呼び出し元のプロセスがフォアグラウンド プロセスです。
    • 呼び出し元のプロセスは、フォアグラウンド プロセスによって開始されました。
    • 現在、フォアグラウンド ウィンドウがないため、フォアグラウンド プロセスはありません。
    • 呼び出し元のプロセスは、最後の入力イベントを受信しました。
    • フォアグラウンド プロセスまたは呼び出し元プロセスのいずれかがデバッグ中です。

これらの条件を満たしていても、フォアグラウンド ウィンドウを設定する権限をプロセスが拒否される可能性があります。

フォアグラウンド ウィンドウを設定できるプロセスでは、AllowSetForegroundWindow 関数を呼び出すか、BSF_ALLOWSFW フラグを指定して BroadcastSystemMessage 関数を呼び出すことによって、別のプロセスでフォアグラウンド ウィンドウを設定できます。 フォアグラウンド プロセスでは、 LockSetForegroundWindow 関数を呼び出すことで、 SetForegroundWindow の呼び出しを無効にすることができます。

所有されている Windows

重なり合ったウィンドウまたはポップアップ ウィンドウは、別の重なり合ったウィンドウまたはポップアップ ウィンドウによって所有できます。 所有されている場合、ウィンドウに複数の制約が設定されます。

  • 所有ウィンドウは、常に z オーダーで所有者の上にあります。
  • 所有者が破棄されると、所有ウィンドウが自動的に破棄されます。
  • 所有者が最小化されると、所有ウィンドウは非表示になります。

所有者ウィンドウとして使用できるのは、重複ウィンドウまたはポップアップ ウィンドウのみです。子ウィンドウを所有者ウィンドウにすることはできません。 アプリケーションは、所有者のウィンドウ ハンドルを CreateWindowExhwndParent パラメーターとして指定して、WS_OVERLAPPEDまたはWS_POPUP スタイルのウィンドウを作成することで、所有ウィンドウ作成します。 hwndParent パラメーターは、重複するウィンドウまたはポップアップ ウィンドウを識別する必要があります。 hwndParent が子ウィンドウを識別する場合、システムは子ウィンドウの最上位の親ウィンドウに所有権を割り当てます。 所有ウィンドウを作成した後、アプリケーションはウィンドウの所有権を別のウィンドウに転送できません。

ダイアログ ボックスとメッセージ ボックスは、既定では所有ウィンドウです。 アプリケーションは、ダイアログ ボックスまたはメッセージ ボックスを作成する関数を呼び出すときに所有者ウィンドウを指定します。

アプリケーションでは、GW_OWNER フラグと共に GetWindow 関数を使用して、ウィンドウの所有者へのハンドルを取得できます。

Z オーダー

ウィンドウの z オーダー は、重なり合うウィンドウのスタック内でのウィンドウの位置を示します。 このウィンドウ スタックは、画面から外に向かって拡張される、虚数軸 (z 軸) に沿って配置されます。 z オーダーの最上位にあるウィンドウは、他のすべてのウィンドウに重なっています。 z オーダーの下部にあるウィンドウは、他のすべてのウィンドウと重なって表示されます。

z オーダーは 1 つのリストに保持されます。 最上位のウィンドウ、最上位レベルのウィンドウ、または子ウィンドウのいずれであるかに基づいて、ウィンドウが z オーダーに追加されます。 一番上のウィンドウは、アクティブ ウィンドウとフォアグラウンド ウィンドウのどちらであっても、他のすべての最上位以外のウィンドウと重なります。 一番上のウィンドウには WS_EX_TOPMOST スタイルがあります。 すべての最上位ウィンドウは、最上位以外のウィンドウの前に z 順に表示されます。 子ウィンドウは、親と z 順にグループ化されます。

アプリケーションがウィンドウを作成すると、システムはウィンドウを同じ種類のウィンドウの z オーダーの先頭に配置します。 BringWindowToTop 関数を使用すると、同じ種類のウィンドウの z オーダーの先頭にウィンドウを表示できます。 SetWindowPos 関数と DeferWindowPos 関数を使用して、z オーダーを再配置できます。

ユーザーは、別のウィンドウをアクティブにして z オーダーを変更します。 システムは、同じ種類のウィンドウの z オーダーの上部にアクティブ ウィンドウを配置します。 ウィンドウが z オーダーの先頭に来るときは、その子ウィンドウも同じになります。 GetTopWindow 関数を使用すると、親ウィンドウのすべての子ウィンドウを検索し、z オーダーで最も高い子ウィンドウにハンドルを返すことができます。 GetNextWindow 関数は、次または前のウィンドウへのハンドルを z オーダーで取得します。

ウィンドウの状態の表示

任意の時点で、ウィンドウはアクティブまたは非アクティブである可能性があります。非表示または表示。最小化、最大化、または復元されます。 これらの品質は、 まとめてウィンドウ表示状態と呼ばれます。 次のトピックでは、ウィンドウの表示状態について説明します。

アクティブ ウィンドウ

アクティブ ウィンドウは、ユーザーが現在作業しているアプリケーションの最上位ウィンドウです。 ユーザーがアクティブウィンドウを簡単に識別できるように、システムはそれを z オーダーの上部に配置し、タイトル バーと境界線の色をシステム定義のアクティブウィンドウの色に変更します。 アクティブ ウィンドウにできるのは、最上位のウィンドウのみです。 ユーザーが子ウィンドウを操作している場合、子ウィンドウに関連付けられている最上位の親ウィンドウがアクティブになります。

システム内の最上位ウィンドウは一度に 1 つだけアクティブです。 ユーザーは、トップレベル ウィンドウ (またはその子ウィンドウのいずれか) をクリックするか、Alt + Esc キーまたは Alt + TAB キーの組み合わせを使用して、最上位ウィンドウをアクティブにします。 アプリケーションは 、SetActiveWindow 関数を呼び出してトップレベル ウィンドウをアクティブにします。 他の関数を使用すると、 SetWindowPosDeferWindowPosSetWindowPlacementDestroyWindow など、別の最上位ウィンドウがアクティブ化される可能性があります。 アプリケーションは、いつでも別のトップレベル ウィンドウをアクティブ化できますが、ユーザーを混乱させないようにするため、ユーザーの操作に応じてのみ有効にする必要があります。 アプリケーションは GetActiveWindow 関数を使用して、アクティブ ウィンドウへのハンドルを取得します。

あるアプリケーションの最上位ウィンドウから別のアプリケーションの最上位ウィンドウにアクティブ化が変更されると、システムは両方のアプリケーションに WM_ACTIVATEAPP メッセージを送信し、変更を通知します。 アクティブ化が同じアプリケーション内の別の最上位ウィンドウに変更されると、システムは両方のウィンドウに WM_ACTIVATE メッセージを送信します。

無効な Windows

ウィンドウは無効にすることができます。 無効になっているウィンドウは、ユーザーからキーボードやマウスの入力を受け取らず、他のウィンドウ、他のアプリケーション、およびシステムからメッセージを受信できます。 通常、アプリケーションはウィンドウを無効にして、ユーザーがウィンドウを使用できないようにします。 たとえば、アプリケーションでダイアログ ボックス内のプッシュ ボタンを無効にして、ユーザーが選択できないようにすることができます。 アプリケーションは、無効なウィンドウをいつでも有効にすることができます。ウィンドウを有効にすると、通常の入力が復元されます。

既定では、作成時にウィンドウが有効になります。 ただし、新しいウィンドウを無効にするには、 アプリケーションでWS_DISABLED スタイルを指定できます。 アプリケーションでは 、EnableWindow 関数を使用して既存のウィンドウを有効または無効にします。 システムは、有効な状態が変更されようとしているときに、 WM_ENABLE メッセージをウィンドウに送信します。 アプリケーションは、 IsWindowEnabled 関数を使用して、ウィンドウが有効になっているかどうかを判断できます。

子ウィンドウが無効になっている場合、システムは子のマウス入力メッセージを親ウィンドウに渡します。 親はメッセージを使用して、子ウィンドウを有効にするかどうかを決定します。 詳細については、「 マウス入力」を参照してください。

キーボード入力を受け取ることができるウィンドウは一度に 1 つだけです。そのウィンドウはキーボードフォーカスを持っていると言われます。 アプリケーションで EnableWindow 関数を使用してキーボード フォーカス ウィンドウを無効にすると、ウィンドウは無効になっているだけでなく、キーボード フォーカスも失われます。 次に、EnableWindow はキーボード フォーカスを NULL に設定します。つまり、ウィンドウにフォーカスがありません。 子ウィンドウまたはその他の子孫ウィンドウにキーボード フォーカスがある場合、親ウィンドウが無効になっていると、子孫ウィンドウはフォーカスを失います。 詳細については、「 キーボード入力」を参照してください。

ウィンドウの表示

ウィンドウは表示または非表示のいずれかにできます。 画面に 表示されるウィンドウ が表示されます。 非表示のウィンドウは描画されずに非表示になります。 ウィンドウが表示されている場合は、そのウィンドウに入力したり、そのウィンドウの出力を確認できます。 ウィンドウが非表示の場合、そのウィンドウは無効になります。 非表示のウィンドウは、システムまたはその他のウィンドウからのメッセージを処理できますが、ユーザーからの入力を処理したり、出力を表示することはできません。 アプリケーションは、ウィンドウの作成時にウィンドウの表示状態を設定します。 後で、アプリケーションで可視性の状態を変更できます。

ウィンドウに WS_VISIBLE スタイルが設定されている場合は、ウィンドウが表示されます。 既定では、アプリケーションでWS_VISIBLEスタイルが指定されていない限り、CreateWindowEx 関数は非表示ウィンドウを作成します。 通常、アプリケーションは、作成プロセスの詳細をユーザーに表示しないようにウィンドウを作成した後、 WS_VISIBLE スタイルを設定します。 たとえば、アプリケーションは、ウィンドウの外観をカスタマイズするときに、新しいウィンドウを非表示にしたままにすることがあります。 CreateWindowExWS_VISIBLE スタイルが指定されている場合、システムは、ウィンドウを作成した後、表示する前に、WM_SHOWWINDOW メッセージをウィンドウに送信します。

アプリケーションは、 IsWindowVisible 関数を使用して、ウィンドウが表示されているかどうかを判断できます。 アプリケーションは、ShowWindow、SetWindowPosDeferWindowPosまたは SetWindowPlacement または SetWindowLong 関数を使用して、ウィンドウを表示 (表示) または非表示にすることができます。 これらの関数は、ウィンドウの WS_VISIBLE スタイルを設定または削除することで、ウィンドウの表示/非表示を切り替えます。 また、 WM_SHOWWINDOW メッセージを表示または非表示にする前に、ウィンドウに送信します。

所有者ウィンドウが最小化されると、関連付けられている所有ウィンドウが自動的に非表示になります。 同様に、所有者ウィンドウが復元されると、関連付けられている所有ウィンドウが自動的に表示されます。 どちらの場合も、システムは WM_SHOWWINDOWメッセージを 非表示または表示する前に、所有ウィンドウに送信します。 場合によっては、アプリケーションで所有者を最小限に抑えたり非表示にしたりすることなく、所有しているウィンドウを非表示にする必要がある場合があります。 この場合、アプリケーションは ShowOwnedPopups 関数を 使用します。 この関数は、すべての所有ウィンドウの WS_VISIBLE スタイルを設定または削除し、 非表示 または表示する前にWM_SHOWWINDOWメッセージを所有ウィンドウに送信します。 所有者ウィンドウを非表示にしても、所有ウィンドウの表示状態には影響しません。

親ウィンドウが表示されている場合は、関連付けられている子ウィンドウも表示されます。 同様に、親ウィンドウが非表示の場合、その子ウィンドウも非表示になります。 親ウィンドウを最小化しても、子ウィンドウの表示状態には影響しません。つまり、子ウィンドウは親ウィンドウと共に最小化されますが、 WS_VISIBLE スタイルは変更されません。

ウィンドウに WS_VISIBLE スタイルがある場合でも、ユーザーは画面にウィンドウを表示できない可能性があります。他のウィンドウが完全に重なっているか、画面の端を越えて移動されている可能性があります。 また、表示される子ウィンドウには、親子関係によって確立されたクリッピング規則が適用されます。 ウィンドウの親ウィンドウが表示されない場合は、ウィンドウも表示されません。 親ウィンドウが画面の端を越えて移動すると、子ウィンドウも移動します。子ウィンドウは親の左上隅を基準にして描画されるためです。 たとえば、子ウィンドウとその親ウィンドウの両方に WS_VISIBLE スタイルがある場合でも、ユーザーは子ウィンドウを表示できない可能性がある、子ウィンドウを含む親ウィンドウを画面の端から十分に離れた場所に移動できます。

最小化、最大化、および復元された Windows

最大化されたウィンドウは、WS_MAXIMIZE スタイルを持つウィンドウです。 既定では、最大化されたウィンドウは画面全体に拡大されます。子ウィンドウの場合は、親ウィンドウのクライアント領域全体に拡大されます。 ウィンドウのサイズは最大化ウィンドウと同じサイズに設定できますが、最大化されたウィンドウは若干異なります。 システムは、ウィンドウのタイトル バーを画面の上部または親ウィンドウのクライアント領域の上部に自動的に移動します。 また、システムは、ウィンドウのサイズ設定の境界線とタイトル バーのウィンドウ配置機能を無効にします (ユーザーがタイトル バーをドラッグしてウィンドウを移動できないようにするため)。

最小化されたウィンドウは、WS_MINIMIZE スタイルを持つウィンドウです。 既定では、最小化されたウィンドウはタスクバー ボタンのサイズに縮小され、タスクバーに移動します。 復元されたウィンドウは、以前のサイズと位置、つまり最小化または最大化される前のサイズに戻されたウィンドウです。

アプリケーションで CreateWindowEx 関数でWS_MAXIMIZEまたはWS_MINIMIZEスタイルを指定した場合、ウィンドウは最初は最大化または最小化されます。 ウィンドウを作成した後、アプリケーションは CloseWindow 関数を使用してウィンドウを最小化できます。 ArrangeIconicWindows 関数は、デスクトップ上のアイコンを配置するか、親ウィンドウの最小化された子ウィンドウを親ウィンドウに配置します。 OpenIcon 関数は、最小化されたウィンドウを以前のサイズと位置に復元します。

ShowWindow 関数を使用すると、ウィンドウを最小化、最大化、または復元できます。 また、ウィンドウの可視性とアクティブ化の状態を設定することもできます。 SetWindowPlacement 関数には ShowWindow と同じ機能が含まれていますが、ウィンドウの既定の最小化、最大化、および復元された位置をオーバーライドできます。

IsZoomed 関数と IsIconic 関数は、特定のウィンドウを最大化するか最小化するかを決定します。 GetWindowPlacement 関数は、ウィンドウの最小化、最大化、および復元された位置を取得し、ウィンドウの表示状態も決定します。

最小化されたウィンドウを最大化または復元するコマンドをシステムが受信すると、ウィンドウに WM_QUERYOPEN メッセージが送信されます。 ウィンドウ プロシージャが FALSE を返す場合、システムは最大化または復元コマンドを無視します。

最大化されたウィンドウのサイズと位置は、最大化されたウィンドウのシステム定義の既定値に自動的に設定されます。 これらの既定値をオーバーライドするには、アプリケーションで SetWindowPlacement 関数を呼び出すか、システムがウィンドウを最大化しようとしているときにウィンドウによって受信される WM_GETMINMAXINFO メッセージを処理します。 WM_GETMINMAXINFO には、最大化されたサイズと位置を設定するためにシステムが使用する値を含む MINMAXINFO 構造体へのポインターが含まれています。 これらの値を置き換えると、既定値がオーバーライドされます。

ウィンドウのサイズと位置

ウィンドウのサイズと位置は、画面または親ウィンドウを基準にした座標で指定された外接する四角形として表されます。 トップレベル ウィンドウの座標は、画面の左上隅を基準とします。子ウィンドウの座標は、親ウィンドウの左上隅を基準にしています。 アプリケーションは、ウィンドウの作成時にウィンドウの初期サイズと位置を指定しますが、ウィンドウのサイズと位置はいつでも変更できます。 詳細については、「 塗りつぶされた図形」を参照してください。

このセクションのトピックは次のとおりです。

既定のサイズと位置

アプリケーションでは、 CreateWindowEx で CW_USEDEFAULTを指定することで、システムが最上位ウィンドウの初期サイズまたは位置を計算できます。 アプリケーションによってウィンドウの座標がCW_USEDEFAULTに設定され、他の最上位ウィンドウが作成されていない場合、システムは画面の左上隅を基準にして新しいウィンドウの位置を設定します。それ以外の場合は、アプリケーションが最後に作成した最上位ウィンドウの位置を基準にして位置を設定します。 width パラメーターと height パラメーターが CW_USEDEFAULT に設定されている場合、新しいウィンドウのサイズが計算されます。 アプリケーションが他の最上位ウィンドウを作成した場合、システムは、新しいウィンドウのサイズを、アプリケーションの最後に作成した最上位ウィンドウのサイズに基づきます。 子ウィンドウまたはポップアップ ウィンドウを作成するときにCW_USEDEFAULTを指定すると、ウィンドウのサイズが既定の最小ウィンドウ サイズに設定されます。

追跡サイズ

システムは、 WS_THICKFRAME スタイルのウィンドウの最小および最大追跡サイズを維持します。このスタイルのウィンドウには、サイズ設定の境界線があります。 最小追跡サイズは、ウィンドウのサイズ設定の境界線をドラッグして生成できる最小のウィンドウ サイズです。 同様に、 最大追跡サイズ は、サイズ変更の境界線をドラッグして生成できる最大のウィンドウ サイズです。

ウィンドウの最小および最大追跡サイズは、システムがウィンドウを作成するときにシステム定義の既定値に設定されます。 アプリケーションでは、既定値を検出し、 WM_GETMINMAXINFO メッセージを処理してオーバーライドできます。 詳細については、「 メッセージのサイズと位置」を参照してください。

システム コマンド

ウィンドウ メニューがあるアプリケーションでは、システム コマンドを送信することで、そのウィンドウのサイズと位置を変更できます。 システム コマンドは、ユーザーがウィンドウ メニューからコマンドを選択したときに生成されます。 アプリケーションは、ウィンドウに WM_SYSCOMMAND メッセージを送信することで、ユーザー アクションをエミュレートできます。 次のシステム コマンドは、ウィンドウのサイズと位置に影響します。

コマンド 説明
SC_CLOSE ウィンドウを閉じます。 このコマンドは、 WM_CLOSE メッセージをウィンドウに送信します。 ウィンドウは、クリーンしてそれ自体を破棄するために必要な手順を実行します。
SC_MAXIMIZE ウィンドウを最大化します。
SC_MINIMIZE ウィンドウを最小化します。
SC_MOVE ウィンドウを移動します。
SC_RESTORE 最小化または最大化されたウィンドウを以前のサイズと位置に復元します。
SC_SIZE size コマンドを開始します。 ウィンドウのサイズを変更するには、マウスまたはキーボードを使用します。

 

サイズ関数と位置関数

ウィンドウを作成した後、アプリケーションは 、SetWindowPlacementMoveWindowSetWindowPosDeferWindowPos など、いくつかの異なる関数のいずれかを呼び出すことによって、ウィンドウのサイズまたは位置を設定できます。 SetWindowPlacement は、ウィンドウの最小化された位置、最大化された位置、復元されたサイズと位置、および表示状態を設定します。 MoveWindow 関数と SetWindowPos 関数は似ています。両方とも、1 つのアプリケーション ウィンドウのサイズまたは位置を設定します。 SetWindowPos 関数には、ウィンドウの表示状態に影響を与えるフラグのセットが含まれています。MoveWindow には、これらのフラグは含まれません。 BeginDeferWindowPosDeferWindowPosおよび EndDeferWindowPos 関数を使用して、サイズ、位置、z オーダーの位置、表示状態など、複数のウィンドウの位置を同時に設定します。

アプリケーションは、 GetWindowRect 関数を使用して、ウィンドウの外接する四角形の座標を取得できます。 GetWindowRect は、ウィンドウの左上隅と右下隅の座標で RECT 構造体を塗りつぶします。 座標は、子ウィンドウの場合でも、画面の左上隅を基準にしています。 ScreenToClient または MapWindowPoints 関数は、子ウィンドウの外接する四角形の画面座標を、親ウィンドウのクライアント領域に対する相対座標にマップします。

GetClientRect 関数は、ウィンドウのクライアント領域の座標を取得します。 GetClientRect は、クライアント領域の左上隅と右下隅の座標で RECT 構造体を塗りつぶしますが、座標はクライアント領域自体に対して相対的です。 つまり、クライアント領域の左上隅の座標は常に (0,0)、右下隅の座標はクライアント領域の幅と高さになります。

CascadeWindows 関数は、デスクトップ上のウィンドウをカスケードするか、指定された親ウィンドウの子ウィンドウをカスケードします。 TileWindows 関数は、デスクトップ上のウィンドウをタイル処理するか、指定された親ウィンドウの子ウィンドウをタイル化します。

メッセージのサイズと位置

システムは、 サイズ または位置が変更されようとしているウィンドウにWM_GETMINMAXINFOメッセージを送信します。 たとえば、ユーザーがウィンドウ メニューから [移動 ] または [ サイズ ] をクリックするか、サイズ変更の境界線またはタイトル バーをクリックすると、メッセージが送信されます。このメッセージは、アプリケーションが SetWindowPos を呼び出してウィンドウを移動またはサイズ変更したときにも送信されます。 WM_GETMINMAXINFO には、ウィンドウの既定の最大化されたサイズと位置、および既定の最小および最大追跡サイズを含む MINMAXINFO 構造体へのポインターが含まれています。 アプリケーションは、 WM_GETMINMAXINFO を処理し、 MINMAXINFO の適切なメンバーを設定することで、既定値をオーバーライドできます。 WM_GETMINMAXINFOを受信するには、ウィンドウに WS_THICKFRAME または WS_CAPTION スタイル 必要です。 WS_THICKFRAME スタイルのウィンドウは、ウィンドウ作成プロセス中、および移動中またはサイズ変更中にこのメッセージを受信します。

システムは 、サイズ 、位置、z オーダー内の位置、または表示状態が変更されようとしているウィンドウに、WM_WINDOWPOSCHANGING メッセージを送信します。 このメッセージには、ウィンドウの新しいサイズ、位置、z オーダーでの位置、および表示状態を指定する WINDOWPOS 構造体へのポインターが含まれています。 WINDOWPOS のメンバーを設定すると、アプリケーションがウィンドウの新しいサイズ、位置、外観に影響を与える可能性があります。

ウィンドウのサイズ、位置、z オーダー内の位置、または表示状態を変更した後、システムは WM_WINDOWPOSCHANGED メッセージをウィンドウに送信します。 このメッセージには、ウィンドウに新しいサイズ、位置、z オーダーでの位置、および表示状態を通知する WINDOWPOS へのポインターが含まれています。 WM_WINDOWPOSCHANGEDで渡される WINDOWPOS 構造体のメンバーを設定しても、ウィンドウには影響しません。 WM_SIZEWM_MOVEメッセージを処理する必要があるウィンドウは、WM_WINDOWPOSCHANGEDDefWindowProc 関数に渡す必要があります。それ以外の場合、システムはWM_SIZEを送信せず、メッセージウィンドウにWM_MOVEします。

ウィンドウの作成時またはサイズ設定時に、 WM_NCCALCSIZE メッセージがウィンドウに送信されます。 システムは、メッセージを使用して、ウィンドウのクライアント領域のサイズと、ウィンドウの左上隅を基準としたクライアント領域の位置を計算します。 ウィンドウは通常、このメッセージを既定のウィンドウ プロシージャに渡します。ただし、このメッセージは、ウィンドウの非クライアント領域をカスタマイズしたり、ウィンドウのサイズを変更するときにクライアント領域の一部を保持したりするアプリケーションで役立ちます。 詳細については、「 描画と描画」を参照してください。

ウィンドウ のアニメーション

AnimateWindow 関数を使用して、ウィンドウを表示または非表示にするときに特殊効果を生成できます。 この方法でウィンドウをアニメーション化すると、 AnimateWindow の呼び出しで指定したフラグに応じて、ウィンドウがロール、スライド、またはフェードされます。

既定では、システムは ロール アニメーションを使用します。 この効果を使用すると、ウィンドウがロールオープン (ウィンドウを表示) またはロールクローズ (ウィンドウを非表示にする) に表示されます。 dwFlags パラメーターを使用して、ウィンドウを水平方向、垂直方向、または斜め方向にロールするかどうかを指定できます。

AW_SLIDE フラグを指定すると、システムはスライド アニメーションを使用します。 この効果を使用すると、ウィンドウが表示され(ウィンドウが表示されている)、または表示外にスライドして表示されます (ウィンドウを非表示にします)。 dwFlags パラメーターを使用して、ウィンドウが水平方向、垂直方向、または斜め方向のいずれにスライドするかを指定できます。

AW_BLENDフラグを指定すると、システムはアルファブレンドフェードを使用します。

また、AW_CENTER フラグを使用して、ウィンドウを内側に折りたたんだり、外側に展開したりするように表示することもできます。

ウィンドウ レイアウトとミラーリング

ウィンドウ レイアウトでは、テキスト オブジェクトと Windows グラフィックス デバイス インターフェイス (GDI) オブジェクトをウィンドウまたはデバイス コンテキスト (DC) でレイアウトする方法を定義します。 英語、フランス語、ドイツ語などの一部の言語では、左から右 (LTR) レイアウトが必要です。 アラビア語やヘブライ語などの他の言語では、右から左 (RTL) のレイアウトが必要です。 ウィンドウ レイアウトはテキストに適用されますが、ビットマップ、アイコン、原点の場所、ボタン、カスケード ツリー コントロール、左右に移動するにつれて水平方向の座標が増加するかどうかなど、ウィンドウの他の GDI 要素にも影響します。 たとえば、アプリケーションが RTL レイアウトを設定した後、原点はウィンドウまたはデバイスの右端に配置され、左に移動すると水平座標を表す数値が増えます。 ただし、すべてのオブジェクトがウィンドウのレイアウトの影響を受けるわけではありません。 たとえば、ダイアログ ボックス、メッセージ ボックス、およびメタファイルやプリンター DC など、ウィンドウに関連付けられていないデバイス コンテキストのレイアウトは、個別に処理する必要があります。 これらの詳細については、このトピックの後半で説明します。

ウィンドウ関数を使用すると、アラビア語版とヘブライ語版の Windows でウィンドウ レイアウトを指定または変更できます。 RTL レイアウト (ミラーリングとも呼ばれます) への変更は、スタイルがCS_OWNDCのウィンドウや 、GM_ADVANCED グラフィック モードの DC ではサポートされないことに注意してください。

既定では、ウィンドウ レイアウトは左から右 (LTR) です。 RTL ウィンドウ レイアウトを設定するには、スタイル WS_EX_LAYOUTRTLを指定して CreateWindowEx を呼び出します。 また、既定では、子ウィンドウ (つまり、createWindow または CreateWindowEx の呼び出しで、WS_CHILD スタイルと有効な親 hWnd パラメーターを使用して作成されたウィンドウ) は、親ウィンドウと同じレイアウトになります。 すべての子ウィンドウへのミラーリングの継承を無効にするには、CreateWindowEx の呼び出しで WS_EX_NOINHERITLAYOUT を指定します。 ミラーリングは、所有ウィンドウ (WS_CHILD スタイルなしで作成されたもの) または CreateWindowEx の親 hWnd パラメーターを使用して作成されたものを NULL に設定した場合には継承されないことに注意してください。 個々のウィンドウのミラーリングの継承を無効にするには、GetWindowLong と SetWindowLong を使用してWM_NCCREATE メッセージを処理して、WS_EX_LAYOUTRTL フラグをオフにします。 この処理は、他に必要な処理に加えて行われます。 次のコード フラグメントは、この方法を示しています。

SetWindowLong (hWnd, 
               GWL_EXSTYLE, 
               GetWindowLong(hWnd,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL))

SetProcessDefaultLayout(LAYOUT_RTL) を呼び出すことで、既定のレイアウトを RTL に設定できます。 呼び出し後に作成されたすべてのウィンドウはミラー化されますが、既存のウィンドウは影響を受けません。 既定のミラーリングをオフにするには、 SetProcessDefaultLayout(0) を呼び出します。

SetProcessDefaultLayout は、ミラー化されたウィンドウの DC のみをミラー化します。 DC をミラーするには、SetLayout(hdc, LAYOUT_RTL) を呼び出します。 詳細については、このトピックで後述する、ウィンドウに関連付けられていないミラーリング デバイス コンテキストに関する説明を参照してください。

ミラー化されたウィンドウ内のビットマップとアイコンも、既定でミラー化されます。 ただし、これらのすべてがミラー化されるわけではありません。 たとえば、テキスト、ビジネス ロゴ、アナログ 時計を使用している場合は、ミラー化しないでください。 ビットマップのミラーリングを無効にするには、 dwLayout に設定されたLAYOUT_BITMAPORIENTATIONPRESERVED ビットを使用して SetLayout を呼び出します。 DC でミラーリングを無効にするには、 SetLayout(hdc, 0) を呼び出します。

現在の既定のレイアウトに対してクエリを実行するには、 GetProcessDefaultLayout を呼び出します。 正常に戻ると、 pdwDefaultLayout には LAYOUT_RTL または 0 が含まれます。 デバイス コンテキストのレイアウト設定に対してクエリを実行するには、 GetLayout を呼び出します。 GetLayout が正常に返されると、LAYOUT_RTLとLAYOUT_BITMAPORIENTATIONPRESERVED ビットの設定によってレイアウト設定を示す DWORD が返されます。

ウィンドウが作成されたら、 SetWindowLong 関数を使用してレイアウトを変更します。 たとえば、ユーザーが既存のウィンドウのユーザー インターフェイス言語をアラビア語またはヘブライ語からドイツ語に変更する場合に、これが必要です。 ただし、既存のウィンドウのレイアウトを変更する場合は、ウィンドウの内容がすべて同じレイアウトで描画されるように、ウィンドウを無効にして更新する必要があります。 次のコード例は、必要に応じてウィンドウ レイアウトを変更するサンプル コードのものです。

// Using ANSI versions of GetWindowLong and SetWindowLong because Unicode
// is not needed for these calls

lExStyles = GetWindowLongA(hWnd, GWL_EXSTYLE);

// Check whether new layout is opposite the current layout
if (!!(pLState -> IsRTLLayout) != !!(lExStyles & WS_EX_LAYOUTRTL))
{
    // the following lines will update the window layout

    lExStyles ^= WS_EX_LAYOUTRTL;        // toggle layout
    SetWindowLongA(hWnd, GWL_EXSTYLE, lExStyles);
    InvalidateRect(hWnd, NULL, TRUE);    // to update layout in the client area
}

ミラーリングでは、"left" と "right" ではなく "near" と "far" の観点から考える必要があります。 これを行わないと、問題が発生する可能性があります。 ミラー化されたウィンドウで問題を引き起こす一般的なコーディング方法の 1 つは、画面座標とクライアント座標の間のマッピング時に発生します。 たとえば、アプリケーションでは、多くの場合、次のようなコードを使用して、ウィンドウにコントロールを配置します。

// DO NOT USE THIS IF APPLICATION MIRRORS THE WINDOW

// get coordinates of the window in screen coordinates
GetWindowRect(hControl, (LPRECT) &rControlRect);  

// map screen coordinates to client coordinates in dialog
ScreenToClient(hDialog, (LPPOINT) &rControlRect.left); 
ScreenToClient(hDialog, (LPPOINT) &rControlRect.right);

これにより、四角形の左端がミラー化されたウィンドウの右端になり、その逆も行われるため、ミラーリングで問題が発生します。 この問題を回避するには、 ScreenToClient 呼び出しを MapWindowPoints の呼び出しに次のように置き換えます。

// USE THIS FOR MIRRORING

GetWindowRect(hControl, (LPRECT) &rControlRect);
MapWindowPoints(NULL, hDialog, (LPPOINT) &rControlRect, 2)

このコードは、ミラーリングをサポートするプラットフォームでは、クライアント ウィンドウがミラー化されるときに左右のポイント座標を入れ替えるために MapWindowPoints が変更されるために機能します。 詳細については、 MapWindowPoints の「解説」セクションを参照してください。

ミラー化されたウィンドウで問題が発生する可能性があるもう 1 つの一般的な方法は、クライアント座標ではなく画面座標のオフセットを使用してクライアント ウィンドウにオブジェクトを配置することです。 たとえば、次のコードでは、クライアント座標の x 位置として画面座標の差を使用して、ダイアログ ボックスにコントロールを配置します。

// OK if LTR layout and mapping mode of client is MM_TEXT,
// but WRONG for a mirrored dialog 

RECT rdDialog;
RECT rcControl;

HWND hControl = GetDlgItem(hDlg, IDD_CONTROL);
GetWindowRect(hDlg, &rcDialog);             // gets rect in screen coordinates
GetWindowRect(hControl, &rcControl);
MoveWindow(hControl,
           rcControl.left - rcDialog.left,  // uses x position in client coords
           rcControl.top - rcDialog.top,
           nWidth,
           nHeight,
           FALSE);

このコードは、ダイアログ ウィンドウに左から右 (LTR) のレイアウトがあり、クライアントのマッピング モードがMM_TEXT場合に問題ありません。これは、クライアント座標の新しい x 位置がコントロールの左端と画面座標のダイアログの違いに対応するためです。 ただし、ミラー化されたダイアログでは、左右が反転するため、代わりに 次のように MapWindowPoints を使用する必要があります。

RECT rcDialog;
RECT rcControl;

HWND hControl - GetDlgItem(hDlg, IDD_CONTROL);
GetWindowRect(hControl, &rcControl);

// MapWindowPoints works correctly in both mirrored and non-mirrored windows.
MapWindowPoints(NULL, hDlg, (LPPOINT) &rcControl, 2);

// Now rcControl is in client coordinates.
MoveWindow(hControl, rcControl.left, rcControl.top, nWidth, nHeight, FALSE)

[ミラーリング] ダイアログ ボックスとメッセージ ボックス

ダイアログ ボックスとメッセージ ボックスはレイアウトを継承しないため、レイアウトを明示的に設定する必要があります。 メッセージ ボックスをミラーするには、MB_RTLREADING オプションを指定して MessageBox または MessageBoxEx を呼び出します。 ダイアログ ボックスを右から左にレイアウトするには、ダイアログ テンプレート構造 DLGTEMPLATEEX で拡張スタイル WS_EX_LAYOUTRTLを使用します。 プロパティ シートは、ダイアログ ボックスの特殊なケースです。 各タブは個別のダイアログ ボックスとして扱われるため、ミラー化するすべてのタブにWS_EX_LAYOUTRTLスタイルを含める必要があります。

ウィンドウに関連付けられていないデバイス コンテキストのミラーリング

メタファイルやプリンター DC など、ウィンドウに関連付けられていない DC はレイアウトを継承しないため、レイアウトを明示的に設定する必要があります。 デバイス コンテキスト のレイアウトを変更するには、 SetLayout 関数を使用します。

SetLayout 関数は、ウィンドウではほとんど使用されません。 通常、ウィンドウは、 WM_PAINT メッセージの処理中にのみ、関連付けられた DC を受け取ります。 場合によっては、 プログラムは GetDC を呼び出してウィンドウの DC を作成します。 いずれの場合も、DC の初期レイアウトは、ウィンドウの WS_EX_LAYOUTRTL フラグに従って BeginPaint または GetDC によって設定されます。

GetWindowOrgExGetWindowExtExGetViewportOrgEx、および GetViewportExtEx によって返される値は、SetLayout の呼び出しの影響を受けません。

レイアウトが RTL の場合、 GetMapMode はMM_TEXTではなくMM_ANISOTROPICを返します。 MM_TEXTで SetMapMode を呼び出すと、正しく機能します。 GetMapMode からの戻り値のみが影響を受けます。 同様に、マッピング モードがMM_TEXTの場合に SetLayout(hdc, LAYOUT_RTL) を呼び出すと、報告されたマッピング モードがMM_ANISOTROPICに変更されます。

ウィンドウの破棄

一般に、アプリケーションは作成するすべてのウィンドウを破棄する必要があります。 これは、 DestroyWindow 関数を使用して行います。 ウィンドウが破棄されると、ウィンドウが表示されている場合はウィンドウが非表示になり、ウィンドウに関連付けられている内部データが削除されます。 これにより、アプリケーションで使用できなくなったウィンドウ ハンドルが無効になります。

アプリケーションは、作成後すぐに作成するウィンドウの多くを破棄します。 たとえば、通常、アプリケーションは、ユーザーがタスクを続行するのに十分な入力を得るとすぐに、ダイアログ ボックス ウィンドウを破棄します。 アプリケーションは最終的に、(終了する前に) アプリケーションのメインウィンドウを破棄します。

ウィンドウを破棄する前に、アプリケーションはウィンドウに関連付けられているデータを保存または削除し、ウィンドウに割り当てられているシステム リソースを解放する必要があります。 アプリケーションがリソースを解放しない場合、システムはアプリケーションによって解放されていないリソースを解放します。

ウィンドウを破棄しても、ウィンドウの作成元のウィンドウ クラスには影響しません。 そのクラスを使用して新しいウィンドウを作成しても、そのクラスの既存のウィンドウは引き続き動作します。 ウィンドウを破棄すると、ウィンドウの子孫ウィンドウも破棄されます。 DestroyWindow 関数は、最初にウィンドウにWM_DESTROY メッセージを送信し、その子ウィンドウと子孫ウィンドウに送信します。 このようにすると、破棄されるウィンドウの子孫ウィンドウもすべて破棄されます。

ユーザーが [閉じる] をクリックすると、ウィンドウ メニューのウィンドウにWM_CLOSEメッセージが表示されます。 このメッセージを処理することで、アプリケーションはウィンドウを破棄する前にユーザーに確認を求めることができます。 ユーザーがウィンドウを破棄する必要があることを確認した場合、アプリケーションは DestroyWindow 関数を呼び出してウィンドウを破棄できます。

破棄されるウィンドウがアクティブウィンドウの場合、アクティブな状態とフォーカス状態の両方が別のウィンドウに転送されます。 アクティブ ウィンドウになるウィンドウは、Alt キーと Esc キーの組み合わせによって決まる次のウィンドウです。 次に、新しいアクティブ ウィンドウによって、キーボード フォーカスを受け取るウィンドウが決まります。