UI オートメーションおよび画面の拡大縮小
更新 : 2007 年 11 月
Windows Vista では、ユーザーがドット/インチ (dpi) 設定を変更して、画面上の多くのユーザー インターフェイス (UI) 要素を大きく表示することができます。この機能は Microsoft Windows で長い間使用可能でしたが、これまでのバージョンでは、スケーリングをアプリケーションで実装する必要がありました。Windows Vista では、独自のスケーリングを処理しないすべてのアプリケーションに対して、Desktop Window Manager が既定のスケーリングを実行します。UI オートメーション クライアント アプリケーションでは、この機能を考慮する必要があります。
このトピックには次のセクションが含まれています。
- Windows Vista のスケーリング
- UI オートメーション クライアントのスケーリング
- 関連トピック
Windows Vista のスケーリング
既定の dpi 設定は 96 です。つまり、概念上は 96 ピクセルが 1 インチの幅や高さに対応します。"インチ" の正確な長さは、モニタのサイズと物理的な解像度に応じて変わります。たとえば、12 インチ幅のモニタを水平方向 1280 ピクセルの解像度で使用すると、96 ピクセルの横線は約 9/10 インチ長くなります。
dpi 設定の変更は、画面の解像度の変更とは異なります。dpi スケーリングでは、画面上の物理的なピクセルの数は変わりません。ただし、UI 要素のサイズと場所にスケーリングが適用されます。このスケーリングは、デスクトップ、およびスケーリングの明示的な拒否を行っていないアプリケーションに対して、Desktop Window Manager (DWM) によって自動的に実行されます。
ユーザーがスケール ファクタを 120 dpi に設定すると、画面上の縦方向または横方向のインチは、25% 大きくなります。これに伴い、すべてのサイズがスケーリングされます。画面の上端および左端からのアプリケーション ウィンドウのオフセットは 25% 増加します。アプリケーションのスケーリングが有効になっていても、アプリケーションが dpi 対応ではない場合、ウィンドウのサイズは、そのウィンドウに含まれるすべての UI 要素のオフセットおよびサイズと共に、同じ割合で増加します。
メモ : |
---|
既定では、ユーザーが dpi を 120 に設定している場合、DWM は dpi 非対応アプリケーションに対してスケーリングを実行しませんが、dpi が 144 以上のカスタム値に設定されている場合はスケーリングを実行します。ただし、ユーザーは既定の動作をオーバーライドできます。 |
画面のスケーリングを行うと、この画面座標に何らかの形で関係しているアプリケーションには新たな課題が生じます。画面には、物理的な座標と論理的な座標の 2 つの座標系が含まれることになります。ある点の物理座標は、原点の左上からの実際のオフセット (ピクセル単位) です。論理座標は、ピクセル自体がスケーリングされた場合のオフセットです。
座標 (100, 48) に、1 つのボタンを含むダイアログ ボックスを設計するとします。このダイアログ ボックスが既定の 96 dpi で表示されると、ボタンは (100, 48) の物理座標に配置されます。120 dpi では、 (125, 60) の物理座標に配置されます。ただし、論理座標は、どの dpi 設定でも同じで、(100, 48) です。
dpi の設定に関係なく、オペレーティング システムとアプリケーションの動作の一貫性を保つ上で、論理座標は重要です。たとえば、Cursor.Position は通常、論理座標を返します。ダイアログ ボックス内の要素の上にカーソルを置くと、dpi の設定に関係なく、同じ座標が返されます。(100, 100) の位置にコントロールを描画すると、コントロールはそれらの論理座標に描画され、どの dpi 設定でも同じ相対位置を占めます。
UI オートメーション クライアントのスケーリング
UI オートメーションAPI は論理座標を使用しません。次のメソッドとプロパティは、物理座標を返すか、またはそれらをパラメータとして受け取ります。
既定では、非 96 dpi 環境で実行されている UI オートメーション クライアント アプリケーションは、これらのメソッドおよびプロパティから正しい結果を取得できません。たとえば、カーソル位置は論理座標内にあるため、クライアントはこれらの座標を単に FromPoint に渡すだけでは、カーソルの下にある要素を取得できません。また、アプリケーションは、クライアント領域外にウィンドウを正しく配置できません。
この解決方法は 2 つの部分で構成されます。
1 つは、クライアント アプリケーションを dpi 対応にします。これを行うためには、起動時に Win32 関数の SetProcessDPIAware を呼び出します。マネージ コードで、次の宣言を使用してこの関数を使用可能にします。
<System.Runtime.InteropServices.DllImport("user32.dll")> _ Friend Shared Function SetProcessDPIAware() As Boolean End Function
[System.Runtime.InteropServices.DllImport("user32.dll")] internal static extern bool SetProcessDPIAware();
この関数は、プロセス全体を dpi 対応にします。つまり、プロセスに属しているすべてのウィンドウはスケーリングされません。たとえば、「蛍光ペンのサンプル」では、強調表示の四角形を構成する 4 つのウィンドウが、論理座標ではなく UI オートメーションから取得された物理座標に配置されます。サンプルが dpi 対応ではない場合、強調表示はデスクトップ上の論理座標に描画され、その結果、非 96 dpi 環境では正しく配置されません。
カーソルの座標を取得するには、Win32 関数の GetPhysicalCursorPos を呼び出します。この関数を宣言して使用する方法を次の例に示します。
Structure CursorPoint Public X As Integer Public Y As Integer End Structure <System.Runtime.InteropServices.DllImport("user32.dll")> _ Friend Shared Function GetPhysicalCursorPos(ByRef lpPoint As CursorPoint) As Boolean End Function Private Function ShowUsage() As Boolean Dim cursorPos As New CursorPoint() Try Return GetPhysicalCursorPos(cursorPos) Catch e As EntryPointNotFoundException ' Not Windows Vista Return False End Try End Function
public struct CursorPoint { public int X; public int Y; } [System.Runtime.InteropServices.DllImport("user32.dll")] internal static extern bool GetPhysicalCursorPos(ref CursorPoint lpPoint); private bool ShowUsage() { CursorPoint cursorPos = new CursorPoint(); try { return GetPhysicalCursorPos(ref cursorPos); } catch (EntryPointNotFoundException) // Not Windows Vista { return false; } }
注意 : |
---|
Cursor.Position は使用しないでください。スケーリング環境におけるクライアント ウィンドウ以外では、このプロパティの動作は未定義です。 |
アプリケーションが dpi 非対応アプリケーションと直接的なプロセス間通信を実行する場合は、Win32 関数の PhysicalToLogicalPoint と LogicalToPhysicalPoint を使用して、論理座標と物理座標間の変換を行うことができます。