WPFアプリの高DPI対応については、前回投稿しました。その中で画像ファイルの個別の対応方法は説明していません。今回はアイコン形式ファイル(icoファイル)の対応方法について投稿します。
アイコンファイル
Windowsの初期のころから使われてきた画像ファイルにアイコンファイルという形式のファイルがあります。このアイコンファイルには、一つのファイルに複数のサイズおよび複数の色数の画像を含むことができます。
たとえば、一つのファイルに
- 16×16, 24×24, 32×32, 48×48, 256×256 などのサイズが異なる複数の画像
- 16色、256色、24ビット色、32ビット色(アルファチャンネル含む)などの色数が異なる複数の画像
などのように、サイズと色数の組み合わせた、複数の画像を含むことができます。
複数のサイズが含むことができるのは、画像を表示するときの品質を向上するためです。表示するときに、表示する領域のサイズに合わせた最適なサイズを選択して表示すると、画像の表示品質劣化につながる拡大・縮小処理を最小限に減らすことができ、表示品質が向上します。
例を挙げるなら、DPIスケール率が100%の場合、Windowsのデスクトップ画面に使用されるアイコンサイズは、32×32のサイズです。ウィンドウのタイトルバーに表示されるアイコンサイズは16×16のサイズです。
この両方の表示に、同じサイズの画像を使用すると表示品質が下がります。たとえば、16×16のサイズの画像を使用して表示したら、タイトルバーは適切な表示となりますが、デスクトップアイコンは拡大表示され荒い表示となります。逆に、32×32のサイズの画像を使用して表示したら、デスクトップアイコンは適切な表示となりますが、タイトルバーのアイコンは縮小表示されることにより、画像がつぶれたりします。
アイコンファイルには複数のサイズの画像を入れることができます。上記の場合、アイコンファイルに16×16サイズの画像と32×32サイズの画像が入っていれば、表示場所のサイズに応じた適切なサイズの画像を使い表示することが可能となり、表示品質が上がります。
色数についても同様な理由で、複数の画像を入れることができました。2000年以前のWindowsでは、グラフィックにおいて24ビット色以上の色数をすべてのシステムでは利用できませんでした。256色や16ビット色などしか利用できないシステムがありました。このようなシステムでは、アイコンファイルに256色の画像や16色の画像が含まれていることが非常に有用でした。しかし、現在のWindowsでは、どのようなシステムでも、24ビット色以上の色数をサポートしています。そのため、適切な色数の画像が使えるという仕組みは、現在ではほとんど利用されていません。
Windowsにおけるアイコンファイルの推奨事項
Windowsにおいては、アイコンファイルを作成するときの推奨事項があります。色数やサイズについて規定 (Icons(英語))されています。
アプリアイコンとしては、以下の色数とサイズの組み合わせを用意することを推奨しています。
- 16色: 16×16, 24×24, 32×32, 48×48, 64×64
- 256色: 16×16, 24×24, 32×32, 48×48, 64×64
- 32ビット色: 16×16, 24×24, 32×32, 48×48, 64×64, 256×256
可能なら、以下のサイズも追加で用意することを推奨しています。
- 追加のサイズ: 8×8, 10×10, 14×14, 22×22, 40×40, 96×96, 128×128
近年では高DPIディスプレイが増え、DPIスケール率が100%より大きいものがほとんどになってきました。場合によってはDPIスケール率が200%を超えるPCもあります。そのため、追加のサイズの中でもサイズが大きい方のサイズは、なるく用意した方がよいと思います。
これらの推奨事項を守ったアイコンファイルでは、デスクトップやエクスプローラー上で表示されるアイコンなどは、表示するときに適切なサイズが利用され、最適な表示がされるようになります。
Windowsが表示するアイコンとアプリが表示するアイコン
表示されるアイコンには、Windowsが表示するアイコンとアプリが表示するアイコンがあります。
Windowsが表示するアイコンは、主にシェルが表示する部分、すなわち、デスクトップやエクスプローラーなどで表示されるアプリアイコンです。
アプリが表示するアイコンは、アプリ内で表示するアイコンです。
Windowsが表示するアイコンは、アイコンファイル内に適切な色数、サイズの画像が含まれていれば、Windows側で適切に表示してくれます。
アプリが表示するアイコンは、アプリ側で表示する領域のサイズに対して、適切なサイズの画像を選択して、表示する必要があります。そのため、アプリ開発者はアイコンファイルを利用するときは、適切なサイズを選択して表示する必要があります。
WPFアプリにおけるアイコンファイル
WPFアプリでのアイコンファイルの利用について考えてみます。
WPFアプリにおいて、アイコンファイルを利用するのは、ほとんどは以下の場所になると思います。
- アプリアイコン(Exeファイルのアイコン)
- WPF XAML内で
Window@Icon
に設定するアイコン - WPF XAML内で
Image@Source
に設定するアイコン
これらの場所で表示には適切なサイズが選択できているのでしょうか?
アプリアイコン
WPFアプリのアプリアイコンは、Visual Studioでは、WPFアプリのプロジェクトのプロパティ設定の中のアプリケーションの項目でアイコンファイルを指定します。ここに設定したアイコンは、Windowsのシェルから利用され、デスクトップ画面やエクスプローラー上で表示するアイコンファイルとして利用されます。ここで設定したアイコンを利用するのは、アプリ側ではなくWindows側です。そのため、サイズや色数の要件を満たす適切なアイコンファイルを用意すさえすれば、Windows側で適切に表示されます。
Window@Iconに設定するアイコン
WPF XAMLのWindow@Icon
には、アイコンファイルを指定することができます。ここで設定したアイコンは、アプリのウィンドウのタイトルバーのアイコンとして使われたり、デスクトップ画面のタスクバーやタスク切り替え画面のアイコンとして使われます。
Image@Sourceに設定するアイコン
WPF XAMLのImage@Source
には、多くの場合、JPEGファイルやPNGファイルを指定して利用します。しかし、このImage@Source
にもアイコンファイルを指定することができます。ここで設定したアイコンは、アプリ内の任意の場所で表示することになります。
アプリ側で表示を制御しなければならないアイコン表示
上記の3つのアイコンファイルの利用箇所のうち、アプリ側で表示を制御しなくてはいけないのは、WPF XAMLで設定したアイコンとなります。EXEに設定するアプリアイコンは、アプリ側では表示に関与しないため、特に気にする必要はありません。
表示に利用されるアイコンサイズ
では、アプリ側で特別な処理をしない場合に、WPF XAML上でアイコンファイルを設定したとき、どのようなサイズのアイコンを利用して表示されるのでしょうか?
- WPF XAML内で
Window@Icon
に設定するアイコン - WPF XAML内で
Image@Source
に設定するアイコン
について調べてみました。
Window@Iconに設定するアイコン
ここに設定したアイコンは以下の場所で使われます。なお、カッコ内に記載したサイズは、DPIスケール率が100%のときのサイズです。
- アプリのウィンドウのタイトルバーのアイコン(16×16)
- タスクバーのアイコン(32×32)
- タスクの切り替え(Alt + Tab)でのアイコン(32×32)
- タスクビュー(Windows ロゴ キー + Tab)でのアイコン(32×32)
WPFアプリでのウィンドウ作成時には、メインディスプレイ(プライマリーディスプレイ)のDPIスケール率に対応したサイズのアイコンが自動的に設定されるようです。
たとえば、メインディスプレイのDPIスケール率が100%のときは、16×16のサイズのアイコンがタイトルバーに使用され、32×32のサイズのアイコンがその他の場所に使われます。DPIスケール率が150%のときは、24×24のサイズのアイコンがタイトルバーに使用され、48×48のサイズのアイコンがその他の場所に使われます。
ただし、アプリの起動中にメインディスプレイのDPIスケール率が変更になった時や、マルチモニター環境で、DPIスケール率がメインディスプレイと異なるモニターへウィンドウが移動したときなど、タイトルバーのアイコンサイズは適切なものが利用されないようです。
すなわち、ウィンドウを作成したタイミングでのみ、メインディスプレイのDPIスケール率のみをチェックし、利用するサイズを決定しているようです。
Image@Sourceに設定するアイコン
ディスプレイのDPIスケール率がいずれの場合であっても、また、表示する領域のサイズがいくつであっても、常にアイコンファイル内の最大サイズのアイコンが表示に利用されます。
アイコンファイル内に256×256サイズのアイコンがあれば、16×16の表示をするときでさえ、256×256サイズのアイコンを縮小表示されます。そのため、かなりつぶれた表示となります。
アプリ側で対応すべき処理
では、アイコンの表示に適切なサイズのアイコンが使われるためには、アプリ側でどのような処理をすればよいのでしょうか?
- WPF XAML内で
Window@Icon
に設定するアイコン - WPF XAML内で
Image@Source
に設定するアイコン
のそれぞれについて考えます。
Window@Iconに設定するアイコン
ここに設定したアイコンは前述した複数の場所で使われます。しかし、対応方法は二種類であるため、以下のように二つに分けて説明します。
- アプリのタイトルバーのアイコン
- アプリのタイトルバー以外のアイコン
アプリのタイトルバーのアイコン
アプリのタイトルバーのアイコンには、DPIスケール率が100%のときは16×16のアイコンを利用します。アプリ側で適切に処理するためには、アプリのウィンドウを表示しているディスプレイのDPIスケール率に合わせたサイズのアイコンを利用する必要があります。
具体的には以下のタイミングで、表示に使用するアイコンのサイズを更新する必要があります。
- アプリのウィンドウを作成したとき
- アプリのウィンドウがDPIスケール率が異なるディスプレイへ移動したとき
上記のタイミングで、ウィンドウを表示しているディスプレイのDPIスケール率を取得して、16×16のサイズをDPIスケール率分だけ大きくしたサイズのアイコンを利用するようにします。
アプリのタイトルバー以外のアイコン
アプリのタイトルバーを除く以下のアイコンは、DPIスケール率が100%のときは、32×32のサイズのアイコンを利用します。
- タスクバーのアイコン(32×32)
- タスクの切り替え(Alt + Tab)でのアイコン(32×32)
- タスクビュー(Windows ロゴ キー + Tab)でのアイコン(32×32)
これらのアイコンは、Windowsのシェルの機能として表示されます。シェルの機能はメインディスプレイに依存した処理になります。そのため、アプリのウィンドウがどのディプレイ上にあるかにかかわらず、常にメインディスプレイのDPIスケール率に対応したサイズのアイコンを利用するようにします。
具体的には以下のタイミングで、表示に使用するアイコンのサイズを更新する必要があります。
- アプリのウィンドウを作成したとき
- メインディスプレイのDPIスケール率が変更になったとき
Image@Sourceに設定するアイコン
Image
コントロールに設定したサイズに合わせたサイズの画像を利用します。WPF XAML上でのWidth
/Height
などのサイズは、96DPI(DPIスケール率100%)を基準としたサイズとなります。そのため、表示に利用する画像のサイズは、Image
コントロールに設定されたサイズをDPIスケール率分だけ大きくした値を利用します。
たとえば、Image
コントロールのサイズが32×32の場合は、DPIスケール率が100%のディスプレイ上では32×32のサイズの画像を利用します。DPIスケール率が150%のディスプレイ上では、1.5倍した48×48のサイズの画像を利用します。
具体的には以下のタイミングで、表示に使用するアイコンのサイズを更新する必要があります。
- Imageコントロールの初期化が完了したとき(始めて表示されたとき)
- Imageコントロールを表示しているアプリのウィンドウがDPIスケール率が異なるディスプレイへ移動したとき
今回は、
- WPF上でアイコンファイルが使われる場所
- WPFの既定での表示の振る舞い
- アプリで処理すべき理想の対処
を確認しました。次回は、実際の処理方法(実装方法)について考えてみたいと思います。