次の方法で共有


画面のスケーリングに関する問題について

Windows Vista 以降のバージョンのオペレーティング システムを使用すると、ユーザーは画面のほとんどの UI 要素が大きく表示されるように、1 インチあたりのドット数 (dpi) の設定を変更できます。 以前のバージョンの Windows では、スケーリングをアプリケーションで実装する必要がありました。 Windows Vista 以降では、デスクトップ ウィンドウ マネージャー (DWM) は、独自のスケーリングを処理しないすべてのアプリケーションに対して既定のスケーリングを実行します。 Microsoft UI オートメーション クライアント アプリケーションでは、この機能を考慮する必要があります。

このトピックは、次のセクションで構成されています。

Windows Vista 以降でのスケーリング

既定の dpi 設定は 96 です。つまり、幅または高さの概念上の 1 インチが 96 ピクセルで占められます。 「インチ」の正確な寸法は、モニターのサイズと物理的な解像度によって異なります。 たとえば、幅 12 インチで水平方向の解像度 1280 ピクセルのモニターでは、96 ピクセルの水平線は 1 インチの約 9/10 の長さになります。

dpi 設定を変更することは、画面の解像度を変更することと同じではありません。 dpi の拡大縮小では、画面上の物理的ピクセル数はそのまま変わりません。 拡大縮小が適用されるのは、UI 要素のサイズと位置です。 このスケーリングは、デスクトップと、スケーリングしないように明示的に要求しないアプリケーションに対して DWM によって自動的に実行できます。

実際には、ユーザーがスケール ファクターを 120 dpi に設定すると、画面上の垂直または水平方向のインチが 25% 拡大されます。 すべての寸法は、それに応じて拡大されます。 画面の上端と左端からのアプリケーション ウィンドウのオフセットが 25% 増加します。 アプリケーションの拡大縮小が有効であり、アプリケーションが dpi 対応でない場合、ウィンドウのサイズと、そこに含まれるすべての UI 要素のオフセットとサイズが同じ比率で大きくなります。

Note

既定では、ユーザーが dpi を 120 に設定した場合、DWM は dpi 対応以外のアプリケーションのスケーリングを実行しませんが、dpi が 144 以上のカスタム値に設定されている場合はスケーリングを実行します。 ただし、この既定の動作は、ユーザーがオーバーライドできます。

 

画面の拡大縮小は、画面座標に何らかの関わりを持つアプリケーションに新しい課題をもたらします。 現在、画面には物理座標と論理座標という 2 つの座標系が含まれています。 ポイントの物理的な座標は、原点の左上からの実際のオフセット (ピクセル単位) です。 論理座標は、ピクセル自体が拡大縮小された場合のオフセットです。

たとえば、ダイアログ ボックスを設計し、座標 (100, 48) にボタンを配置するとします。 このダイアログ ボックスが既定の 96 dpi で表示される場合、ボタンは物理座標 (100, 48) に位置します。 120 dpi の場合は、物理座標 (125, 60) に位置します。 しかし、論理座標は dpi の設定に関係なく、(100, 48) のままです。

論理座標は、dpi の設定に関係なく、オペレーティング システムとアプリケーションの動作を一貫性のあるものにするため、重要です。 たとえば、通常、 GetCursorPos 関数は 論理座標を返します。 ダイアログ ボックス内の要素の上にカーソルを移動すると、dpi の設定に関係なく、同じ座標が返されます。 (100, 100) にコントロールを描画する場合、それはこの論理座標に描画され、dpi の設定に関係なく、同じ相対位置を占めることになります。

UI オートメーション クライアントにおける拡大縮小

UI オートメーション API は論理座標を使用しません。 次のメソッドとプロパティは、物理座標を返すか、物理座標をパラメーターとして受け取ります。

既定では、96 dpi に設定されていない環境で実行されているUI オートメーションアプリケーションは、これらのメソッドとプロパティから正しい結果を取得しません。 たとえば、カーソル位置は論理座標であるため、クライアントは IUIAutomation::ElementFromPoint にこれらの座標を渡して、カーソルの下にある要素を取得できません。 さらに、アプリケーションはクライアント領域外にウィンドウを正しく配置することもできません。

このソリューションには、2 つの部分があります。

まず、クライアント アプリケーションを dpi 対応にします。 これを行うには、起動時に SetProcessDPIAware 関数を呼び出します。 この関数は、プロセス全体を dpi 対応にします。つまり、プロセスに属するすべてのウィンドウは拡大縮小されません。

次に、カーソル座標を取得するには、 GetPhysicalCursorPos 関数を 呼び出します。