Top  上へ  目次



Ver.18.5系の話


 18系は短命になりそうだなぁ・・・とは思いつつ、もう次の話です。

高DPI環境対応

 DPI、どっと・ぱー・いんちの略でして、ピクセルの密度の話ですね。
 高解像度ディスプレイだと画面の拡縮を行うので、滲んだり、画像がつぶれたり、表示が極小になってしまうという現象についてです。

 これ完結編になると良いなとは思っていますが、きっとエンドレスだと思います。
 ほんとMicrosoft社さんの迷走っぷりといったらもう・・・ええ加減バシっと決めてくれ・・・とは思ってます。
 十数年もこんな状況なので、Windowsアプリ作るのって、もはや苦行なんですよねぇ。


 さてWindowsアプリケーションのDPI認識をおさらいしておくと、現状はこんな感じのモードが存在しています。
モード搭載時期概要
未対応XP以前、DPI認識をしないあらゆるディスプレイのDPIを96×96固定のものとして扱う
高解像度ディスプレイで見ると小さすぎるか滲みが酷いものとなります
システム対応Windows Vistaで搭載されたモード
起動時のモニタのDPI値を使用
奇麗だけど、複数のモニタをまたぐと強制的に未対応
モニタごと ver.1Windows 8.1で搭載されたモードすごい奇麗、開発者が大変すぎてやる気になりにくいレベル
モニタごと ver.2Windows 10(1703) 搭載されたモードすごい奇麗、開発者が大変すぎて匙投げるレベル Ver.2
GDIスケーリングWindows 10(1809)から搭載されたモード
別名「混合モード」や「システム(拡張)」
そこそこ奇麗、部分的に奇麗にならない
未対応のアプリもソコソコ奇麗になるのが素敵
 今までAs/Rは「システム対応」になっていました。
 今更感は無きにしも非ずですが、というのもWindows Server 2016、初期のWindows 10と同じ世代のやつです。
 こちらのサポートをしていたがため、踏み切れなかったという事情がありました。
 で、シェアの下がり具合も気にしていましたが「そもそもサーバーOSでモニタを繋がないでしょ?ましてやマルチディスプレイとか皆無です」と言われて、納得してしまいました。
 という訳で、Microsoft社もサポートを打ち切ったWindows 10(1809)以降で使える「GDIスケーリング」モードへ切り替えていくことを検討しています。
 Windows 10もそろそろ終わりが見えてきましたしね・・・


 実際の所、「GDIスケーリング」モード自体、かなり中途半端な仕組みになっているので、ディスプレイ1個の場合を考えるとあまりメリットがありません。
 複数モニタも、概ね自動で調整してくれますよ、というのはスゴイ技術だと思いますが、他のOSと比較するとまだまだ足らんよというものです。
 どう考えても、現在無いもの(画素)を補うのは無理があると思いますが、そのうちAIで足らない画素を補うとかやらかすんじゃないかなぁ、という気はしています。
 まぁ、永遠に過渡期のつもりで、今回の対応も進めています。

 以下の画像は300%に拡大しています。
 「システム」の場合、DPI比の異なるディスプレイにウィンドウを動かすと滲んで見えるようになる欠点があります。

●メインメニュー付近
 上の段が、既存の「システム」モードでの描画、DPIは192×192で認識しています。
 下の段が、既存の「GDIスケーリング」モードでの描画、DPIは96×96で認識しています。

 大きな違いを述べると、ファイル(F)などが書かれているメインメニューの部分は、上の段のシステムの方が奇麗です。
 このメインメニューはMFC側で描画しているものでして、残念ながら何ともなりません。
 メインメニュー自体を廃止の検討していた要因の一つでもあります。

 それに対してツールバーの画像は下の段のGDIスケーリングモードの方がシャープに見えます。
 こちらもMFC描画ですが、何故かGDIスケーリングに対応しているものとなります。
 またこちらはDPI比の異なるディスプレイにウィンドウを動かしても、ほぼ差がないように見えるのがポイントです。

 なおアドレスバーの左側、「←」「→」「↑」などのアイコン画像は、私の方で描画してるので両方とも同じように見えているというものになります。


●フォルダーバー
 こちらも上段が「システム」下段が「GDIスケーリング」です。

 文字は大差ないかなぁ。
 下段の方がやや大きめに描画されている他は、「Android」の圧縮フォルダーを示すオーバーレイアイコン(「-><-」こんなやつ)の滲み具合が気になります。
 あと操作してみないと気付かないですが、枠線が微妙に太くなっておりマウスでのウィンドウサイズ変更がしやすい、というのがポイント高いです。

●外部コマンド
 こちらも上段が「システム」下段が「GDIスケーリング」です。

 上段の方は「処理開始時にファイルの出力先を開く(J)」の表示が見切れているのが分かると思います。
 「システム」は144×144でも、見えるように・・・と作られてるので、192×192だとこういった表示があちこちで発生します。



 対応の仕方としては「お前のDPI値は96×96だ」と騙してマニフェストに定義する形なので、運用で「システム」に戻すことが可能だと考えてます。
 具体的には、ショートカットのプロパティ、互換性のタブの「高DPI設定の変更」で調整できたりします。
 気に入らなきゃ、ここいじってね、になるのかなとも思いました。
 この辺のカスタマイズって、知らない人の方が多くて・・・うーん、なので悩ましいところです。
 使う側の観点からすると「DPIとか意識させる方が間違っており、アプリ側で当然対応しておくべきだろ」と思います。
 開発する側の観点からすると、「DPIとか意識させる方が間違っており、OS側で当然対応しておくべきだろ」なのですが・・・



追記

 マニフェスト定義教えて!という要望があったので、実際に使ってる定義ファイルです。
 コメントアウトの状況を見ると、色々調査したアレコレが垣間見えるかと思います。

 なおVisual studioを使ってる方は、ビルドオプションの中に選択肢がある場合もありますので注意してください。
 ビルドオプションを無効にしておかないと、今後どちらが優先されるようになるか分かりません。
 あとVisual studio 2022では、ビルドオプションの方にはUnaware GDI Scaledが選択肢に存在していません。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">

  <asmv3:application>

    <!-- このブロックを未指定にするとUnaware -->

    <!-- システム(System Aware) -->
    <!--<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>-->

    <!--モニタごと対応にする(Per-monitor Aware Version 1)-->
    <!--asmv3:windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>
    </asmv3:windowsSettings-->

    <!--モニタごとV2対応にする(Per-monitor Aware Version 2)-->
    <!--asmv3:windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
    </asmv3:windowsSettings-->

    <!-- GDIスケーリングを有効にする(Unaware GDI Scaled)-->
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">
      <gdiScaling>true</gdiScaling>
    </asmv3:windowsSettings>
  </asmv3:application>

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
      <!-- Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
      <!-- Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
      <!-- Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
      <!-- Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
    </application>
  </compatibility>
</assembly>