Mixed-Mode DPI スケーリングと DPI 対応 Api

Sub-Process DPI 認識サポート

SetThreadDpiAwarenessContext を使用すると、1つのプロセス内でさまざまな DPI スケーリングモードを使用できます。 Windows 10 記念日更新の前に、ウィンドウの DPI 認識がプロセス全体の DPI 認識モード (DPI 非対応、システム DPI 対応、または Per-Monitor DPI 対応) にバインドされました。 しかし、 SetThreadDpiAwarenessContext では、トップレベルのウィンドウは、プロセス全体の dpi 認識モードとは異なる dpi 認識モードを持つことができます。 これは、子ウィンドウにも影響します。これは、子ウィンドウが常に親ウィンドウと同じ DPI 認識モードになるためです。

SetThreadDpiAwarenessContext を使用すると、開発者は、デスクトップアプリケーションの DPI 固有の動作を定義するときに、開発作業に専念する場所を決めることができます。 たとえば、アプリケーションのプライマリトップレベルウィンドウはモニターごとにスケーリングできますが、セカンダリトップレベルウィンドウはオペレーティングシステムによるビットマップスケーリングによって拡張できます。

DPI 認識コンテキスト

SetThreadDpiAwarenessContext が使用可能になる前に、プロセスの DPI 認識は、アプリケーションバイナリのマニフェストで、またはプロセスの初期化中に SetProcessDpiAwarenessを呼び出すことによって定義されました。 SetThreadDpiAwarenessContext では、各スレッドは、プロセス全体の dpi 認識モードとは異なる場合がある個別の dpi 認識コンテキストを持つことができます。 スレッドの DPI 認識コンテキストは、* * * * dpi _ 認識 _ コンテキスト * * * * 型で表され、次のように動作します。

  • スレッドは、いつでも、その DPI 認識コンテキストを変更することができます。
  • コンテキストが変更された後に行われたすべての API 呼び出しは、対応する DPI コンテキストで実行されます (仮想化される可能性があります)。
  • ウィンドウが作成されると、その DPI 認識は、その時点での呼び出し元スレッドの DPI 認識として定義されます。
  • ウィンドウのウィンドウプロシージャが呼び出されると、スレッドは、ウィンドウの作成時に使用されていた DPI 認識コンテキストに自動的に切り替えられます。

SetThreadDpiAwarenessContext を使用する一般的なシナリオは次のとおりです。1つのコンテキストで実行されているスレッド ( _ モニターが _ _ _ _ 認識する dpi 認識コンテキスト など) では、一時的に別のコンテキストに切り替え、ウィンドウを作成してから、スレッドコンテキストを直前の状態に戻します。_ _ _ 作成されたウィンドウでは、dpi _ 認識 _ コンテキストが _ 認識 されません。一方、呼び出し元スレッドのコンテキストは、 SetThreadDpiAwarenessContext の後続の呼び出しで認識される _ _ _ _ モニター _ ごとに dpi 認識コンテキスト に復元されます。 このシナリオでは、呼び出し元のスレッドに関連付けられているウィンドウがモニターごとのコンテキストで実行され (オペレーティングシステムによってビットマップが拡張されることはありません)、新しく作成されたウィンドウは DPI に対応していません (したがって、画面に自動的にビットマップが拡大され、>100% scaling)。

図1は、メインプロセススレッドが _ _ _ _ モニターごとの dpi 認識コンテキスト で実行され、そのコンテキストを dpi _ 認識 _ コンテキスト _ に切り替え、新しいウィンドウを作成する方法を示しています。 次に、新しく作成されたウィンドウは、メッセージがディスパッチされるたびに、または API 呼び出しが行われるときに _ _ _ 認識 されない dpi 認識コンテキストで実行されます。 新しいウィンドウを作成した直後に、メインスレッドは、 _ _ _ _ モニターごとに DPI 認識コンテキスト の前のコンテキストに復元されます。

モニターごとの dpi 認識の動作を示す図

SetThreadDpiAwarenessContext が提供する1つのプロセス内でのさまざまな dpi 認識モードのサポートに加えて、次の dpi 固有の機能がデスクトップアプリケーションに追加されました。

Enablenonclient/* * * *

注意

モニターごとの V2 DPI 認識モードでは、この機能が自動的に有効になります。そのため、これを使用するアプリケーションでは、 Enablenonclient\n を呼び出す必要はありません。

Windows の WM NCCREATE handler 内から Enablenonclient を呼び 出す _ と、トップレベルウィンドウの非クライアント領域が自動的に DPI にスケーリングされます。 最上位レベルのウィンドウがモニターごとの DPI 対応 (プロセス自体がモニターごとの dpi に対応しているか、またはモニターごとの dpi 対応スレッド内でウィンドウが作成されたため) である場合、これらのウィンドウのキャプションバー、スクロールバー、メニュー、およびメニューバーは、ウィンドウの DPI が変更されるたびに DPI スケールになります

子の編集コントロールの非クライアントスクロールバーなど、子ウィンドウの非クライアント領域は、この API を使用した場合、DPI スケールは自動的には行われないことに注意してください。

注意

EnablenonclientNCCREATE Iscaling は、 WM _ ハンドラーから呼び出す必要があります。

* ForDpi Api
  • GetSystemMetricsなど、頻繁に使用されるいくつかの api には HWND のコンテキストがないため、戻り値に対して適切な DPI 認識をと判断することはできません。 異なる DPI 認識モードまたはコンテキストで実行されているスレッドからこれらの Api を呼び出すと、呼び出し元のスレッドのコンテキストに合わせてスケーリングされていない値が返されることがあります。 * * * * GetSystemMetricForDpi ** * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * を引数として dpi を取得し、現在のスレッドのコンテキストから dpi 認識を推論します

  • GetSystemMetricForDpiSystemParametersInfoForDpi は、次の式に従って、DPI でスケーリングされたシステムメトリック値とシステムパラメーター値を返します。

    GetSystemMetrics (...) @ dpi = = GetSystemMetricsForDpi (..., dpi)

    したがって、特定のシステム DPI 値を持つデバイスで実行されているときに GetSystemMetrics (または SystemParametersInfoForDpi) を呼び出すと、入力と同じ dpi 値が与えられた場合、dpi 対応のバリアント (GetSystemMetricsForDpiSystemParametersInfoForDpi) と同じ値が返されます。

  • AdjustWindowRectExForDpi は HWND を受け取り、DPI を区別する方法でウィンドウの四角形の必要なサイズを計算します。

GetDpiForWindow
GetDpiForWindowは、指定された HWND に関連付けられている DPI を返します。 この答えは、HWND の DPI 認識モードによって異なります。
HWND の DPI 認識モード 戻り値
互い 96
システム システム DPI
Per-Monitor 関連付けられたトップレベルウィンドウが主に配置されているディスプレイの DPI
(子ウィンドウが指定されている場合は、対応するトップレベルの親ウィンドウの DPI が返されます)
GetDpiForSystem

Getdpiforsystem の呼び出しは、システムの DPI を取得するために、 GetDCGetDeviceCapsを呼び出すよりも効率的です。

サブプロセス DPI 認識を使用するアプリケーションで実行されている可能性のあるコンポーネントは、プロセスのライフサイクル中にシステム DPI が静的であると想定しないでください。 たとえば、 dpi _ 認識 _ コンテキスト _ で実行されているスレッドがシステム DPI を照会する場合、応答は96になります。 ただし、同じスレッドが dpi _ 認識 _ コンテキスト _ システム 認識コンテキストに切り替えられ、システム DPI に再びクエリを実行した場合、答えは異なる可能性があります。 キャッシュされた (または古くなる可能性がある) システム DPI 値が使用されないようにするには、 Getdpiforsystem を使用して、呼び出し元のスレッドの dpi 認識モードに対して相対的なシステム dpi を取得します。