アクティブなアクセシビリティと Windows Vista 画面のスケーリング

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

Windows Vista での拡大縮小

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

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

実際には、ユーザーがスケール ファクターを 120 dpi に設定すると、画面上の垂直または水平方向のインチが 25% 拡大されます。 すべての寸法は、それに応じて拡大されます。 画面の上端と左端からのウィンドウのオフセットが 25% 増加します。 ウィンドウのサイズは、同じ割合で増加し、それに含まれるすべての UI 要素のオフセットとサイズも増加します。

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

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

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

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

アクティブなアクセシビリティ クライアントでのスケーリング

Microsoft Active Accessibility では論理座標は使用されません。 次のメソッドと関数は、物理座標を返すか、パラメーターとして受け取ります。

既定では、96 dpi 以外の環境で実行されている Microsoft Active Accessibility クライアント アプリケーションは、これらの呼び出しから正しい結果を取得できません。 たとえば、カーソル位置は論理座標であるため、クライアントはこれらの座標を AccessibleObjectFromPoint に渡して、カーソルの下にある要素を取得することはできません。

さらに、フォーカスされた UI 要素を強調表示するアクセシビリティ アプリケーションなど、クライアント領域の外部にウィンドウを作成するアプリケーションでは、ウィンドウは、 IAccessible::accLocation によって返される物理座標ではなく論理座標に配置されるため、正しい画面位置にウィンドウを作成しません。

このソリューションは、次の 2 つの部分に分かれています。

  • クライアント アプリケーションを "dpi 対応" にします。 これを行うには、起動時に SetProcessDPIAware 関数を呼び出します。 この関数は、プロセス全体を dpi 対応にします。つまり、プロセスに属するすべてのウィンドウは拡大縮小されません。
  • dpi 対応の関数を使用します。 たとえば、カーソル座標を取得するには、 GetPhysicalCursorPos 関数を 呼び出します。 GetCursorPos を使用しないでください。dpi 対応アプリケーションでの動作は未定義です。

アプリケーションが dpi 対応以外のアプリケーションとの直接のクロスプロセス通信を実行する場合は、PhysicalToLogicalPoint 関数と LogicalToPhysicalPoint 関数を使用して論理座標と物理座標を変換できます。