A5:SQL Mk-2

開発のこと、日々のこと

A5:SQL Mk-2における高DPIアプリケーション開発

| 1件のコメント

A5:SQL Mk-2は一応高DPI対応ということになっていますが、これまで私の開発環境は高DPIに耐えうるディスプレイではありませんでした。1680×1050という少し変則的な解像度のディスプレイ(フルHDですらない)を2枚使って、高解像度のテストのときだけ無理やり、スケーリングを150%とかにしてみたり…。

ということで、今回4Kディスプレイを2枚導入してみました。なかなかこれ自体大変だったのですが、今回の書くのは高DPI対応アプリケーションのお話。

Windowsにおける高DPI対応は以下の3つのレベルがあります。

  • Not DPI Aware (高DPI対応無し)
  • System DPI Aware (高DPI対応あり、ただしモニターごとのDPI対応無し)
  • Per monitor DPI Aware (高DPI対応あり、モニターごとのDPI対応あり)

Not DPI Aware は内部的には古いWindowsの標準DPIである96DPIで内部的に描画され、スケーリング(拡大)されて実際のモニターに表示されます。このため高解像度のモニターでは文字や画像がモヤっとして表示されます。高DPIに何も対応しないアプリケーションはこれになります。

System DPI Aware は起動時にDPI値が決定(多分メインモニターのDPI値)され文字はきれいに表示されます。画像ももやっとしません(個別に画像を用意する必要があります)。DPIの異なるモニターに切り替わるときはシステムが自動的にスケーリング表示に切り替える仕組みとなります。ただし、Windows 10(の最近のバージョン)ではスケーリング表示時でも文字だけはきれいに描画されます。アプリケーションでは、起動時にレイアウトの調整をしたり、解像度にあわせた複数の画像を用意する必要があります。

Per monitor DPI Awareは Windows 8.1から導入され、一番新しい対応レベルです。モニターを移動するごとにDPIの変更がアプリケーションに伝達され、アプリケーション内でDPI切り替えの処理が実行されます。アプリケーションでは、起動時とDPI切り替えである、WM_DPICHANGEDイベントでレイアウト調整や画像の切り替え処理をする必要があります。

A5:SQL Mk-2 Version 2.14系ではPer monitor DPI Awareに対応していました。開発環境である Delphi 10.2 も Per monitor DPI Aware に対応することになっています。ただ、実際DPI値の異なるモニター間の切り替え動作は正しく動作していなかったようです。A5:SQL Mk-2が今どき珍しいMDIアプリケーションであることも影響しているかもしれません。

色々試してみたのですが、なかなか完全対応は難しいようです。また、DPI切り替えの処理は複数ドキュメントを開いていると結構時間のかかる処理のようで、切替処理にモタついてしまうのもなんだかいけません。

これらのことから A5:SQL Mk-2では一つレベルを落とし、 System DPI Awareに変更することにしました。これなら、DPIの異なるモニター間を移動しても画面崩れなどは起きませんし、切り替え時にアプリケーションがモタつくこともありません。実際やってみて、表示もなかなかきれいに表示されているように思います。

実際のやり方は 以下の通り。

これまでは、Delphiのプロジェクトオプションで「アプリケーション」の「高 DPI の有効化」にチェックを入れていましたが、

System DPI Awareにするには、マニフェストファイルを自分で用意するようにします。

実際のマニフェストファイルの記述は以下の通り…。「<dpiAware>true</dpiAware>」というのが、 System DPI Aware に対応する記述です。

<?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" >
  <dependency> 
    <dependentAssembly> 
        <assemblyIdentity 
            type="win32" 
            name="Microsoft.Windows.Common-Controls" 
            version="6.0.0.0" 
            processorArchitecture="*" 
            publicKeyToken="6595b64144ccf1df" 
            language="*" 
        /> 
    </dependentAssembly>
  </dependency> 
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- 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}"/>
      <!-- Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
  </compatibility>
</assembly>

1件のコメント

  1. 長くて何が書きたかったかブレた書き方になったかもだけど、つまりは

    高DPIアプリケーションの開発は Per monitor DPI Aware にするのが理想だけど、アプリケーションの要件によっては System DPI Aware でも良いかもよ?ってお話です。

コメントを残す

必須欄は * がついています