DPIスケーリングの形式とWindowsフォームの自動スケーリング

 1年ほど前に「DPIスケール変更時におけるWPFとSilverlightの違い」という投稿をしました。この投稿では、Windowsフォームに関する説明があまりなく、かつDPIスケーリングの設定部分の説明が不足していましたので、この投稿でそれを補足するかたちにしたいと思います。


スケーリングの拡大率とスケーリングの形式(デスクトップ側)


 以前の投稿でも、DPIスケーリングには2つの形式があり、それはスケーリングの値によってどちらがデフォルトとなるかが変わると説明しました。以下のように書いています。

これは[カスタム DPI 設定]画面で「Windows XP 形式の DPI スケーリングを使用する」にチェックが入っているかどうかで決まります。126%より小さいの場合、このチェックボックスはデフォルトでオンになりますが、126%以上の場合はデフォルトでオフになります。



 この説明自体は間違いではありませんが、[カスタム DPI 設定]画面は[ディスプレイ]画面からさらに[カスタムサイズ変更オプション]をクリックして開く画面であり、一般的なユーザーが意識する設定ではありません。多くのユーザーはデフォルト設定のまま(そもそもスケーリングを意識しない)か、設定を変更したとしても[ディスプレイ]画面の[小 - 100%]、[中 - 125%]、[大 - 150%]の3種類から選択することになります。


 [ディスプレイ]画面からスケーリングを設定する場合、DPIスケーリングの形式はどうなるのでしょうか。それは、結局のところ[カスタムサイズ変更オプション]におけるデフォルトに従い、以下のようになります。

小 - 100% XP形式のスケーリング
中 - 125% XP形式のスケーリング
大 - 150% DPI仮想化



 つまり、[大 - 150%]でXP形式のスケーリングという設定は、[ディスプレイ]画面からはできません。[カスタム DPI 設定]画面を開いて設定する必要があります。そしてDPI仮想化の場合、システムによってビットマップ的(画像処理的)に拡大が行われますので、アプリケーションやアプリケーションフレームワーク側で考慮すべき要素は一切ありません(もちろん以前の投稿で書いたように、設定やマニフェストでそのアプリケーションだけDPI仮想化を無効にすることは可能です)。


 以前の投稿で、グレープシティのコンポーネントは、125%のWindows XP形式のスケーリングをサポートしている(動作確認、および一部スケーリング対応機能を追加)とご紹介したのは、これが理由です。

アプリケーション開発支援ツール/コンポーネント/ライブラリ | Developer Tools - グレープシティ株式会社
高DPI対応
高精細ディスプレイが普及するに伴い、エンドユーザーがOSのDPIをカスタマイズして画面サイズを拡大することが予想されています。拡大率によってはアプリケーションのレイアウトが崩れるなどの問題が発生することもあり、これに対応を迫られた場合開発サイドに大きな負担がかかります。
InuputManではDPI スケーリングによる拡大について、125%のWindows XP形式のスケーリングをサポートします。OS側のDPI設定が変更されると、製品のコントロールサイズなどを自動調整し、アプリケーションのレイアウトが崩れるのを防ぎます



 WindowsフォームのDPIスケーリング対応


 このあたりの話についてセッションではご紹介していましたが、blogには書いていませんでしたのであためてここに記載します。なお、以下はすべて.NET Framework 2.0以降のWindowsフォームの場合です。


 Windowsフォームは、アプリケーションプラットフォームとしてDPIスケーリングに対応する機能を持っています。

Windows フォームにおける自動スケーリング | Microsoft Docs



 まず、Windowsフォームの自動スケーリングのカギとなるのは、フォームのAutoScaleModeプロパティです。このプロパティがFontかDpiの場合、システムのDPIスケーリングに合わせてフォームもスケーリングされます。ちなみに、このプロパティのクラスの既定値はNoneですが、Visual StudioWindowsフォームのプロジェクトテンプレートではNoneではなく、初めからFontが設定されています(少なくとも2010と2012ではそうなっていることを確認)ので注意が必要です。


 自動スケーリングは、設計時の大きさ(AutoScaleDimensions プロパティ)と、実行時の大きさ(CurrentAutoScaleDimensions プロパティ)を比較し、そこから比率(AutoScaleFactor プロパティ)を計算して、その比率分フォームの読み込み時にスケールさせる(PerformAutoScale メソッド )という仕組みになっています。


 そして、AutoScaleModeプロパティがFont場合にはフォントサイズが、DPIの場合にはDPIスケーリングのサイズが比率の算出に使用されます。そもそもシステムのDPIスケーリングを大きくすると、それに合わせてシステムのフォントサイズも大きくなるため、FontでもDpiでもおおむね同じようにスケーリングが行われます。しかし、Fontの場合にはシステムのフォントサイズだけでなく、プログラム的にフォームのフォントサイズを変更した場合でもスケール処理が行われて(フォント変更時にもPerformAutoScaleメソッドが呼び出されて)しまいます。ですから、単純にシステムのDPIスケーリングに合わせてフォームを自動スケーリングさせたい場合には、AutoScaleModeプロパティはDpiに設定するのが良いでしょう。


 ここまでの話では、Windowsフォームの自動スケーリングは、システムのDPIに合わせて適切に動作し、何も問題がないように思うかもしれませんが、以下のような注意点があります。

  1. 異なるシステムフォントサイズ/DPI設定の 環境でプロジェクトを共有できない
  2. フォームが読み込まれる時やフォームのフォント変更時など、特定のタイミングでのみスケール処理が行われるため、 実行時にピクセルサイズを設定する場合には、 DPIの比率を乗算してやる必要がある(単位系まではスケールされない)
  3. スケール結果は 各コントロールのScaleメソッドの処理に依存



 WPFのようにプラットフォーム全体の単位系がスケールされるわけではないため、コントロール側でスケール処理を実装していなければ、スケーリングは行われません。また、どのようにスケールする(どこまできちんとスケールさせる)かは、そのコントロールの作り手に依存します。


 下の図は、.NET標準のDataGridViewとSPREAD for Windows Forms 7.0Jの両方で、100%と125%のときの表示を比較したものです。DataGridViewは、コントロール全体の大きさとフォントなどは125%にスケールしていますが、列の幅、行の高さは100%の時のままであることが分かります。一方、SPREADの場合、今回の新バージョンで列の幅や行の高さもスケールするモードを新たに追加しているため、125%でもレイアウトは100%のときと同様になっていることを確認できます。









宣伝


 グレープシティの以下の製品は、125%のWindows XP形式のスケーリングをサポートしています。