この概要では、ウィンドウの種類、状態、サイズ、位置などのウィンドウの機能について説明します。
ウィンドウの種類
このセクションには、ウィンドウの種類について説明する次のトピックが含まれています。
ウィンドウの重なり
重なり合うウィンドウは、タイトル バー、境界線、クライアント領域を持つ最上位ウィンドウ (子以外のウィンドウ) です。これは、アプリケーションのメイン ウィンドウとして機能することを目的とします。 また、ウィンドウ メニュー、最小化ボタンと最大化ボタン、スクロール バーを含めることもできます。 メイン ウィンドウとして使用される重なり合ったウィンドウには、通常、これらのコンポーネントがすべて含まれます。
CreateWindowEx 関数でWS_OVERLAPPEDまたはWS_OVERLAPPEDWINDOWスタイルを指定すると、アプリケーションによってウィンドウが重なって作成されます。 WS_OVERLAPPED スタイルを使用する場合、ウィンドウにはタイトル バーと罫線が表示されます。 WS_OVERLAPPEDWINDOW スタイルを使用する場合、ウィンドウにはタイトル バー、サイズ変更罫線、ウィンドウ メニュー、最小化ボタンと最大化ボタンがあります。
ポップアップ ウィンドウ
ポップアップ ウィンドウは、ダイアログ ボックス、メッセージ ボックス、およびアプリケーションのメイン ウィンドウの外部に表示されるその他の一時的なウィンドウに使用される、特殊な種類の重なり合ったウィンドウです。 タイトル バーはポップアップ ウィンドウでは省略可能です。それ以外の場合、ポップアップ ウィンドウは 、WS_OVERLAPPED スタイルの重なったウィンドウと同じです。
ポップアップ ウィンドウを作成するには、CreateWindowEx でWS_POPUPスタイルを指定します。 タイトル バーを含めるには、 WS_CAPTION スタイルを指定します。 WS_POPUPWINDOW スタイルを使用して、罫線とウィンドウ メニューを含むポップアップ ウィンドウを作成します。 ウィンドウ メニューを表示するには、WS_CAPTION スタイルをWS_POPUPWINDOW スタイルと組み合わせる必要があります。
子ウィンドウ
子ウィンドウにはWS_CHILD スタイルがあり、親ウィンドウのクライアント領域に限定されます。 通常、アプリケーションは子ウィンドウを使用して、親ウィンドウのクライアント領域を機能領域に分割します。 子ウィンドウを作成するには、CreateWindowEx 関数でWS_CHILDスタイルを指定します。
子ウィンドウには親ウィンドウが必要です。 親ウィンドウには、重なるウィンドウ、ポップアップ ウィンドウ、または別の子ウィンドウを指定できます。 CreateWindowEx を呼び出すときに親ウィンドウを指定します。 CreateWindowEx でWS_CHILD スタイルを指定しても、親ウィンドウを指定しない場合、ウィンドウは作成されません。
子ウィンドウにはクライアント領域がありますが、明示的に要求されない限り、他の機能はありません。 アプリケーションでは、タイトル バー、ウィンドウ メニューを要求したり、子ウィンドウのボタン、境界線、スクロール バーを最小化および最大化したりできますが、子ウィンドウにはメニューを含めることはできません。 アプリケーションでメニュー ハンドルが指定されている場合は、子ウィンドウ クラスを登録するとき、または子ウィンドウを作成するときに、メニュー ハンドルは無視されます。 罫線スタイルが指定されていない場合、罫線のないウィンドウが作成されます。 アプリケーションでは、境界のない子ウィンドウを使用して、親ウィンドウのクライアント領域を分割しながら、分割をユーザーに対して非表示にすることができます。
このセクションでは、子ウィンドウの次の側面について説明します。
ポジショニング
システムは常に、親ウィンドウのクライアント領域の左上隅を基準にして子ウィンドウを配置します。 子ウィンドウの一部が親ウィンドウの境界線の外側に表示されることはありません。 アプリケーションが親ウィンドウより大きい子ウィンドウを作成するか、子ウィンドウの一部または全部が親の境界線を超えるように子ウィンドウを配置する場合、システムは子ウィンドウをクリップします。つまり、親ウィンドウのクライアント領域の外側の部分は表示されません。 親ウィンドウに影響を与えるアクションは、次のように子ウィンドウにも影響します。
| 親ウィンドウ | 子ウィンドウ |
|---|---|
| 破壊された | 親ウィンドウが破棄される前に破棄されます。 |
| 隠れた | 親ウィンドウを非表示にする前に非表示にします。 子ウィンドウは、親ウィンドウが表示されている場合にのみ表示されます。 |
| 移動されました | 親ウィンドウのクライアント領域と共に移動しました。 子ウィンドウは、移動後にクライアント領域を描画します。 |
| 表示 | 親ウィンドウが表示された後に表示されます。 |
クリッピング
システムは、親ウィンドウのクライアント領域から子ウィンドウを自動的にクリップしません。 つまり、親ウィンドウが子ウィンドウと同じ場所に描画を実行すると、子ウィンドウの上に描画されます。 ただし、親ウィンドウに WS_CLIPCHILDREN スタイルがある場合、システムは親ウィンドウのクライアント領域から子ウィンドウをクリップします。 子ウィンドウがクリップされている場合、親ウィンドウはその上に描画できません。
子ウィンドウは、同じクライアント領域内の他の子ウィンドウと重なることがあります。 1 つ以上の他の子ウィンドウと同じ親ウィンドウを共有する子ウィンドウは、 兄弟ウィンドウと呼ばれます。 子ウィンドウの 1 つが WS_CLIPSIBLINGS スタイルを持っている場合を除き、兄弟ウィンドウは互いのクライアント領域に描画できます。 子ウィンドウにこのスタイルがある場合は、子ウィンドウ内にある兄弟ウィンドウの任意の部分がクリップされます。
ウィンドウに WS_CLIPCHILDREN または WS_CLIPSIBLINGS スタイルがある場合、パフォーマンスが若干低下します。 各ウィンドウはシステム リソースを占有するため、アプリケーションでは子ウィンドウを無差別に使用しないでください。 最適なパフォーマンスを得るために、メイン ウィンドウを論理的に分割する必要があるアプリケーションは、子ウィンドウを使用するのではなく、メイン ウィンドウのウィンドウ プロシージャで行う必要があります。
親ウィンドウとの関係
アプリケーションは 、SetParent 関数を呼び出すことによって、既存の子ウィンドウの親ウィンドウを変更できます。 この場合、システムは古い親ウィンドウのクライアント領域から子ウィンドウを削除し、新しい親ウィンドウのクライアント領域に移動します。 SetParent で NULL ハンドルが指定されている場合、デスクトップ ウィンドウは新しい親ウィンドウになります。 この場合、子ウィンドウはデスクトップ上で、他のウィンドウの境界線の外側に描画されます。 GetParent 関数は、子ウィンドウの親ウィンドウへのハンドルを取得します。
親ウィンドウはクライアント領域の一部を子ウィンドウに放棄し、子ウィンドウはこの領域からすべての入力を受け取ります。 ウィンドウ クラスは、親ウィンドウの子ウィンドウごとに同じである必要はありません。 つまり、アプリケーションは、異なる外観の子ウィンドウで親ウィンドウを埋め、さまざまなタスクを実行できます。 たとえば、ダイアログ ボックスにはさまざまな種類のコントロールを含めることができます。各コントロールには、ユーザーのさまざまな種類のデータを受け入れる子ウィンドウがあります。
子ウィンドウには親ウィンドウが 1 つだけありますが、親ウィンドウには任意の数の子ウィンドウを含めることができます。 各子ウィンドウは、さらに子ウィンドウを持つことができます。 このウィンドウチェーンでは、各子ウィンドウは元の親ウィンドウの子孫ウィンドウと呼ばれます。 アプリケーションは IsChild 関数を使用して、特定のウィンドウが子ウィンドウであるか、特定の親ウィンドウの子孫ウィンドウであるかを検出します。
EnumChildWindows 関数は、親ウィンドウの子ウィンドウを列挙します。 次に、 EnumChildWindows は 、アプリケーション定義のコールバック関数に各子ウィンドウにハンドルを渡します。 特定の親ウィンドウの子孫ウィンドウも列挙されます。
Messages
システムは、子ウィンドウの入力メッセージを子ウィンドウに直接渡します。メッセージは親ウィンドウを介して渡されません。 唯一の例外は、子ウィンドウが 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 拡張ウィンドウスタイルがある場合、レイヤードウィンドウの形状は無視され、マウスイベントはレイヤードウィンドウの下の他のウィンドウに渡されます。
メッセージ専用ウィンドウ
メッセージのみのウィンドウを使用すると、メッセージを送受信できます。 表示されず、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 を呼び出すプロセスは、UWP アプリや Windows 8 または 8.1 用に設計された Windows ストア アプリではなく、デスクトップ アプリケーションに属しています。
- 前景プロセスは、LockSetForegroundWindow関数の以前の呼び出しによって、SetForegroundWindowの呼び出しを無効にしていません。
- フォアグラウンド ロックタイムアウトの有効期限が切れています (SystemParametersInfoのSPI_GETFOREGROUNDLOCKTIMEOUTを参照してください)。
- アクティブなメニューはありません。
- さらに、次の条件のうち少なくとも 1 つが当てはまります。
- 呼び出し元のプロセスがフォアグラウンド プロセスです。
- 呼び出しプロセスは、フォアグラウンドプロセスによって開始されました。
- 現在、フォアグラウンド ウィンドウがないため、フォアグラウンド プロセスはありません。
- 呼び出し元のプロセスは、最後の入力イベントを受信しました。
- フォアグラウンド プロセスまたは呼び出し元プロセスのいずれかがデバッグ中です。
これらの条件を満たしている場合でも、フォアグラウンド ウィンドウを設定する権限をプロセスが拒否される可能性があります。
フォアグラウンド ウィンドウを設定できるプロセスでは、AllowSetForegroundWindow 関数を呼び出すか、BSF_ALLOWSFW フラグを指定して BroadcastSystemMessage 関数を呼び出すことによって、別のプロセスでフォアグラウンド ウィンドウを設定できます。 フォアグラウンド プロセスでは、 LockSetForegroundWindow 関数を呼び出すことによって、 SetForegroundWindow の呼び出しを無効にすることができます。
所有しているWindowsのバージョン
重なり合ったウィンドウまたはポップアップウィンドウは、別の重なり合ったウィンドウやポップアップウィンドウに属することがあります。 所有されている場合、1 つのウィンドウに複数の制約が設定されます。
- 所有しているウィンドウは、常に Z 順序で所有者より上にあります。
- 所有者が破棄されると、所有ウィンドウが自動的に破棄されます。
- 所有者が最小化されると、対象のウィンドウは非表示になります。
所有者ウィンドウにできるのは、重複するウィンドウまたはポップアップ ウィンドウだけです。子ウィンドウを所有者ウィンドウにすることはできません。 アプリケーションは、所有者のウィンドウ ハンドルを CreateWindowEx の hwndParent パラメーターとして指定して、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 関数を呼び出して最上位ウィンドウをアクティブにします。 その他の関数により、 SetWindowPos、 DeferWindowPos、 SetWindowPlacement、 DestroyWindow など、別の最上位ウィンドウがアクティブ化される可能性があります。 アプリケーションはいつでも別の最上位レベルのウィンドウをアクティブ化できますが、ユーザーを混乱させないように、ユーザーの操作に応じてのみ有効にする必要があります。 アプリケーションは GetActiveWindow 関数を使用して、アクティブ ウィンドウへのハンドルを取得します。
あるアプリケーションの最上位ウィンドウから別のアプリケーションの最上位ウィンドウにアクティブ化が変更されると、システムは両方のアプリケーションに WM_ACTIVATEAPP メッセージを送信し、変更を通知します。 アクティブ化が同じアプリケーション内の別の最上位ウィンドウに変更されると、システムは両方のウィンドウに WM_ACTIVATE メッセージを送信します。
無効な Windows
ウィンドウは無効にすることができます。 無効になっているウィンドウは、ユーザーからキーボードやマウスの入力を受け取っていませんが、他のウィンドウ、他のアプリケーション、およびシステムからメッセージを受信できます。 通常、アプリケーションはウィンドウを無効にして、ユーザーがウィンドウを使用できないようにします。 たとえば、アプリケーションでダイアログ ボックスのプッシュ ボタンを無効にして、ユーザーが選択できないようにすることができます。 アプリケーションはいつでも無効なウィンドウを有効にすることができます。ウィンドウを有効にすると、通常の入力が復元されます。
既定では、ウィンドウは作成時に有効になります。 ただし、アプリケーションは WS_DISABLED スタイルを指定して、新しいウィンドウを無効にすることができます。 アプリケーションでは、 EnableWindow 関数を使用して既存のウィンドウを有効または無効にします。 システムは、有効な状態が変更されようとしているときに、 WM_ENABLE メッセージをウィンドウに送信します。 アプリケーションは、 IsWindowEnabled 関数を使用してウィンドウが有効かどうかを判断できます。
子ウィンドウが無効になっている場合、システムは子のマウス入力メッセージを親ウィンドウに渡します。 親はメッセージを使用して、子ウィンドウを有効にするかどうかを決定します。 詳細については、「 マウス入力」を参照してください。
キーボード入力を受け取ることができるウィンドウは一度に 1 つだけです。そのウィンドウはキーボードフォーカスを持っていると言われます。 アプリケーションで EnableWindow 関数を使用してキーボード フォーカス ウィンドウを無効にすると、ウィンドウは無効になっているだけでなく、キーボード フォーカスも失われます。 次に、EnableWindow はキーボード フォーカスを NULL に設定します。つまり、フォーカスを持つウィンドウはありません。 子ウィンドウまたはその他の子孫ウィンドウにキーボード フォーカスがある場合、親ウィンドウが無効になっていると、子孫ウィンドウはフォーカスを失います。 詳細については、「 キーボード入力」を参照してください。
ウィンドウの表示
ウィンドウは、表示または非表示にすることができます。 画面に 目に見えるウィンドウ が表示されます。 隠れているウィンドウは、描画されないことによって非表示になります。 ウィンドウが表示されている場合、ユーザーはウィンドウに入力を指定し、ウィンドウの出力を表示できます。 ウィンドウが非表示の場合は、実質的に無効になります。 非表示ウィンドウは、システムまたは他のウィンドウからのメッセージを処理できますが、ユーザーからの入力を処理したり、出力を表示したりすることはできません。 アプリケーションは、ウィンドウの作成時にウィンドウの表示状態を設定します。 後で、アプリケーションで可視性の状態を変更できます。
ウィンドウの WS_VISIBLE スタイルが設定されている場合は、ウィンドウが表示されます。 既定では、アプリケーションでWS_VISIBLEスタイルが指定されていない限り、CreateWindowEx 関数は非表示ウィンドウを作成します。 通常、アプリケーションは、作成プロセスの詳細をユーザーに表示しないようにウィンドウを作成した後、 WS_VISIBLE スタイルを設定します。 たとえば、アプリケーションは、ウィンドウの外観をカスタマイズする間、新しいウィンドウを非表示のままにすることができます。 CreateWindowEx でWS_VISIBLE スタイルが指定されている場合、システムは、ウィンドウを作成した後、表示する前に、WM_SHOWWINDOW メッセージをウィンドウに送信します。
アプリケーションは 、IsWindowVisible 関数を使用してウィンドウが表示されるかどうかを判断できます。 アプリケーションは、ShowWindow、SetWindowPos、DeferWindowPos、または SetWindowPlacement または SetWindowLong 関数を使用して、ウィンドウを表示 (表示) または非表示にすることができます。 これらの関数は、ウィンドウの WS_VISIBLE スタイルを設定または削除することで、ウィンドウの表示と非表示を切り替えます。 また、表示または非表示にする前に、 WM_SHOWWINDOW メッセージをウィンドウに送信します。
所有者ウィンドウが最小化されると、関連付けられている所有ウィンドウが自動的に非表示になります。 同様に、所有者ウィンドウが復元されると、関連付けられている所有ウィンドウが自動的に表示されます。 どちらの場合も、システムは WM_SHOWWINDOWメッセージを 非表示または表示する前に所有ウィンドウに送信します。 場合によっては、アプリケーションで所有者を最小限に抑えたり非表示にしたりすることなく、所有しているウィンドウを非表示にする必要がある場合があります。 この場合、アプリケーションは ShowOwnedPopups 関数を 使用します。 この関数は、すべての所有ウィンドウの WS_VISIBLE スタイルを設定または削除し、 WM_SHOWWINDOW メッセージを非表示または表示する前に所有するウィンドウに送信します。 所有者ウィンドウを非表示にしても、所有しているウィンドウの表示状態には影響しません。
親ウィンドウが表示されている場合は、関連付けられている子ウィンドウも表示されます。 同様に、親ウィンドウが非表示の場合、その子ウィンドウも非表示になります。 親ウィンドウを最小化しても、子ウィンドウの表示状態には影響しません。つまり、子ウィンドウは親と共に最小化されますが、 WS_VISIBLE スタイルは変更されません。
ウィンドウに WS_VISIBLE スタイルがある場合でも、ユーザーは画面にウィンドウを表示できない可能性があります。他のウィンドウが完全に重なっているか、画面の端を越えて移動されている可能性があります。 また、表示される子ウィンドウは、その親子関係によって確立されたクリッピング ルールの対象となります。 ウィンドウの親ウィンドウが表示されていない場合は、そのウィンドウも表示されません。 親ウィンドウが画面の端を越えて移動すると、子ウィンドウは親の左上隅を基準にして描画されるため、子ウィンドウも移動します。 たとえば、子ウィンドウとその親ウィンドウの両方に WS_VISIBLE スタイルがある場合でも、子ウィンドウを含む親ウィンドウを、ユーザーが子ウィンドウを表示できない可能性がある画面の端から十分に離れた場所に移動できます。
最小化、最大化、復元されたウィンドウ
最大化されたウィンドウは、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に設定し、他のトップレベルウィンドウを作成していない場合、システムは画面の左上隅を基準にして新しいウィンドウの位置を設定します。それ以外の場合は、アプリケーションが最後に作成した最上位ウィンドウの位置を基準にして位置を設定します。 幅と高さのパラメーターがCW_USEDEFAULTに設定されている場合、新しいウィンドウのサイズが計算されます。 アプリケーションが他の最上位レベルのウィンドウを作成した場合、システムは、新しいウィンドウのサイズを、アプリケーションの最後に作成された最上位ウィンドウのサイズに基づきます。 子ウィンドウまたはポップアップ ウィンドウを作成するときにCW_USEDEFAULTを指定すると、システムはウィンドウのサイズを既定の最小ウィンドウ サイズに設定します。
追跡サイズ
システムは、 WS_THICKFRAME スタイルのウィンドウの最小および最大追跡サイズを維持します。このスタイルのウィンドウには、サイズ設定の境界線があります。 最小追跡サイズは、ウィンドウのサイズ変更の境界線をドラッグして生成できる最小のウィンドウ サイズです。 同様に、 最大の追跡サイズ は、サイズ変更の境界線をドラッグして生成できる最大のウィンドウ サイズです。
ウィンドウの最小および最大追跡サイズは、システムがウィンドウを作成するときにシステム定義の既定値に設定されます。 アプリケーションは、既定値を検出し、 WM_GETMINMAXINFO メッセージを処理してオーバーライドできます。 詳細については、「 メッセージのサイズと位置」を参照してください。
システム コマンド
ウィンドウ メニューがあるアプリケーションでは、システム コマンドを送信することで、そのウィンドウのサイズと位置を変更できます。 システム コマンドは、ユーザーがウィンドウ メニューからコマンドを選択したときに生成されます。 アプリケーションは、ウィンドウに WM_SYSCOMMAND メッセージを送信することで、ユーザー アクションをエミュレートできます。 次のシステム コマンドは、ウィンドウのサイズと位置に影響します。
| コマンド | Description |
|---|---|
| SC_CLOSE | ウィンドウを閉じます。 このコマンドは、 WM_CLOSE メッセージをウィンドウに送信します。 ウィンドウは、自身をクリーンアップし破棄するために必要な手順を実行します。 |
| SC_MAXIMIZE | ウィンドウを最大化します。 |
| SC_MINIMIZE | ウィンドウを最小化します。 |
| SC_MOVE | ウィンドウを移動します。 |
| SC_RESTORE | 最小化または最大化されたウィンドウを以前のサイズと位置に復元します。 |
| SC_SIZE | size コマンドを開始します。 ウィンドウのサイズを変更するには、マウスまたはキーボードを使用します。 |
サイズ関数と位置関数
ウィンドウを作成した後、アプリケーションは 、SetWindowPlacement、 MoveWindow、 SetWindowPos、 DeferWindowPos など、いくつかの異なる関数のいずれかを呼び出すことによって、ウィンドウのサイズまたは位置を設定できます。 SetWindowPlacement は、ウィンドウの最小化された位置、最大化された位置、復元されたサイズと位置、および表示状態を設定します。 MoveWindow 関数と SetWindowPos 関数は似ています。両方とも、1 つのアプリケーション ウィンドウのサイズまたは位置を設定します。 SetWindowPos 関数には、ウィンドウの表示状態に影響するフラグのセットが含まれています。MoveWindow には、これらのフラグは含まれません。 BeginDeferWindowPos、DeferWindowPos、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_SIZEおよびWM_MOVEメッセージを処理する必要があるウィンドウは、defWindowProc 関数にWM_WINDOWPOSCHANGEDを渡す必要があります。それ以外の場合、システムは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 のアラビア語とヘブライ語のバージョンでウィンドウ レイアウトを指定または変更できます。 スタイルが CS_OWNDC のウィンドウや、GM_ADVANCED グラフィック モードの DC では、RTL レイアウト (ミラーリングとも呼ばれます) への変更はサポートされないことに注意してください。
既定では、ウィンドウ レイアウトは左から右 (LTR) です。 RTL ウィンドウ レイアウトを設定するには、スタイル WS_EX_LAYOUTRTLを指定して CreateWindowEx を呼び出します。 また、既定では、子ウィンドウ (つまり、WS_CHILD スタイルで作成され、CreateWindow または CreateWindowEx の呼び出しで有効な親 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 を作成することがあります。 いずれの場合も、ウィンドウの WS_EX_LAYOUTRTL フラグに従って 、BEGINPaint または GetDC によって DC の初期レイアウトが設定されます。
GetWindowOrgEx、GetWindowExtEx、GetViewportOrgEx、および 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 キーの組み合わせによって決まる次のウィンドウです。 次に、新しいアクティブ ウィンドウによって、キーボード フォーカスを受け取るウィンドウが決まります。