Windowsには,GDIベースのアプリケーションが高解像度ディスプレイでも鮮明に表示されるようにするための表示スケールという仕組みがあります。GDIは,Windowsネイティブアプリで2Dグラフィックを描画するための標準的なAPIのひとつで,高解像度ディスプレイ以前から存在し,テキスト・アイコン・図形・画像といった2Dグラフィックを常に96 DPIで描画するように設計されています。GDIで描画した画面が高解像度ディスプレイで縮小されないようにするためには,実際のDPIに合わせて画像を拡大する必要があります。画面がぼやけて表示されるのはそのためです。
Creators Update(Windows 10 1703)では,この現象を改善するため,GDIスケーリングという仕組みが導入されました。アプリの表示スケールの修正で表示がぼやける可能性があるといわれている一部のデスクトップアプリは,GDIで画面を描画しているアプリのことを指しています。4Dは,GDIとDirect2D(高解像度ディスプレイに対応したAPI)を併用しているので,これに該当します。
高解像度ディスプレイ(4Kなど)を搭載したノートパソコンに標準的な外部モニター(1080pなど)を接続し,デスクトップを拡大しているユーザーは少なくありません。その場合,ノートパソコンは解像度を200%(192 DPI)に設定し,外部モニターは100%(96 DPI)のまま使用する,といったことができます。従来のスケーリングでは,物理的なサイズを再現するため,画面の解像度に合わせて画像を引き伸ばしていました。そのように拡大された画像は,96 DPIのデータしか持ち合わせていないため,おおきなピクセルで表示されたり,ぼやけて表示されたりします。
ディスプレイ毎のDPIを考慮し,場面に合わせて動的に画像データを差し替えるようにアプリが設計されていれば良いのですが,高解像度ディスプレイ以前から存在するGDIアプリは,そのような仕組みを持っていません。GDIスケーリングは,アプリの代わりにシステムがスケーリングするので,DPIを意識したプログラミングをしなくても良い,というメリットがあります。特にテキストの表示が改善されます。
GDIに限らず,Windowsアプリには,下記のDPIモードが用意されています。
DPIを気にしない。100%(96 DPI)を前提に描画します。その他の解像度は想定されていません。
システムDPIに合わせる。ユーザーがログインした時点におけるメイン画面のDPIを前提に描画します。メイン画面は鮮明に描画されますが,その他のモニターは表示がぼやける可能性があります。
モニター毎のDPIに合わせる。モニターのDPIに合わせて描画します。正しく開発されていれば,モニター間でウィンドウを移動しても,鮮明に画面が表示されます。
ウィンドウ別にDPIを管理する。上述したモードを組み合わせてアプリを開発することができます。
High DPI Desktop Application Development on Windows
GDIスケーリングは,実際のDPIと同等以上(x2, x3, x4など)の解像度でテキストやベクトル図形をレンダリングした後,Desktop Window Manager (DWM) が合成したビットマップを画面に表示するというものです。画面の解像度96の倍数であれば,DWMは使用されません。いずれにしても,単純な拡大よりも鮮明な表示が期待できます。96 DPIのデータしか持ち合わせていないビットマップ画像は,引き延ばされてレンダリングされるため,ぼやけて表示されます。また,実際のDPIが96の倍数でなかった場合,単純な拡大ほどではありませんが,テキストやベクトル図形であっても,ぼやけて表示されるという限界があります。
GDIスケーリングは,おもにテキストの表示を鮮明にすることを意図した仕組みですが,一部の文字は端のピクセルが欠落されて表示されないことがあります。たとえば,10ptのフォントを200%の画面に表示する場合,20ptのフォントが2倍の領域にレンダリングされますが,フォントや文字の種別により,テキストの線が「太く」なれば,表示領域の幅が200%を超えることがあるためです。
前述したモードとGDIスケーリングの関係は,下記のとおりです。
DPIを気にしない: GDIスケーリングは適用されません。
システムDPIに合わせる: システムDPIよりも高解像度の外部モニターであっても,GDIスケーリングが適用されることにより,図形とテキストの表示が改善されます。システムDPIは,ユーザーがログインした時点におけるメイン画面のDPIなので,途中でメイン画面を別のディスプレイに切り替えたり,メイン画面の解像度を変更した場合,従来のスケーリングは再ログインするまで表示がぼやけたままになりました。GDIスケーリングが有効であれば,システムがDPIの変更を検出するので,自動的に表示が調整されます。
モニター毎のDPIに合わせる: すでに高解像度ディスプレイを意識したアプリであれば,GDIスケーリングを使用する必要はないはずです。テキストや図形はもちろんのこと,ビットマップ画像もDPIに合わせたものを使用しているので,GDIスケーリングよりも鮮明に画面が描画されます。これには,チェックボックスやポップアップメニューのキャレット(実際にはビットマップ画像)も含まれます。カーニング(隣接する文字の距離の計算)も係数を掛けるのではなく,実際のフォントサイズに基づいて計算されるため,GDIスケーリングよりも自然になります。このようなアプリでは,GDIスケーリングを無効にしたいと思うでしょう。判断の材料として,それぞれのモードでアプリを実行して詳細な点を比較することができます。
アプリには,開発者が設定したデフォルトの表示モードがありますが,「プロパティ>互換性>高 DPI 設定の変更」で上書きすることもできます。「システム(拡張)」がGDIスケーリングです。4D v18は,このモードに設定されています。「アプリケーション」に設定した場合,スケーリングが無効となります。「システム」は,Creators Update(Windows 10 1703)以前のスケーリングです。
ユーザーは,プロパティで自由にスケーリングの設定を変更することができます。,IT管理者は,System Center Configuration Manager (SCCM) やMicrosoft IntuneでGDIスケーリングのポリシーを設定することにより,これを制御したいと考えるかもしれません。
参考資料
Improving the high-DPI experience in GDI based Desktop Apps
前述したように,4DはGDIとDirect2Dを併用しています。GDIスケーリングを無効にした場合,Direct2Dで描画されている部分は鮮明に表示され,そうでない部分は96 DPIの位置とサイズにレンダリングされます。「システムスタイルシート」は自動的に調整されますが,その他のフォントサイズは絶対値で計算されるので,文字が小さくなります。スケーリングが適用されないため,画面のレイアウトは変わりますが,すべて鮮明に表示されるというメリットがあります。
既知の問題
MDIウィンドウの「閉じるボタン」上でマウスポインターを移動すると,ボタンが高速で点滅するという現象が報告されています。これはGDIスケーリングの不具合であることがわかっています。「高 DPI 設定」を「アプリケーション」に変更した場合,あるいは96 DPIの画面であれば,問題は発生しません。
具体的には,GDIスケーリングで描画されているウィンドウのウィンドウプロセスマネージャーで,WM_NCMOUSEMOVE
メッセージ処理中にWindowFromPoint
を呼び出した場合,ボタンのハイライト表示がリセットされることがわかっています。
Mac/Windowsの違いを吸収し,過去のバージョンでデザインされたフォーム等を高解像度ディスプレイで同じように表示するためには,WindowsのGDIスケーリングを利用するのが,現状,最良のソリューションであるように思われます。4D側でこの現象を解消することは困難かもしれません。