HSPで高DPI対応ソフトを作ろう

プログラミング
スポンサーリンク

こんにちは!

久しぶりにHSPの記事を書きたいと思います!
今回は、HSPの高DPI対応です。


はじめに

高DPIとはなんぞや、という説明をします。

昔のディスプレイは、1ドットのサイズが細かくないため、
1ピクセル=1ドットのような設計がほとんどでした。
そして、1ピクセルの大きさも、どのディスプレイもだいたい同じようなサイズ(96dpi)でした。
従って、ソフトを作る際に、1ドット=1ピクセルの前提で、GUIの設計をしていました。

ただ5、6年前ぐらいから、スマホが高繊細化してきており、
ディスプレイもRatinaディスプレイや4kディスプレイなど、高繊細なものが登場してきました。

例をあげると、次のようなものがあります。
Apple MacBook Pro 解像度 2560×1600、227dpi
Microsoft Surface Pro 解像度 2736×1824 、267 dpi
iiyama 4Kディスプレイ B2875UHSU-B1A 解像度 3840×2160、157 dpi

このように、96dpiより大きなものを高DPI(High DPI)と呼びます。

高DPIに対応していないソフトの問題点

このような高密度なディスプレイで、
これまで作成したソフトを実行するとどうなるでしょう。

高DPIで動作することを考えていないソフトの場合は、
OSがソフトのGUIを自動的にスケーリングして表示することとなります。

しかし、このスケーリングが問題でして、
ASCII.jp Windows 10+高解像度ディスプレイでのアプリのボケはRS2で解消される」のように
文字や画像がボケてしまうのです。

高DPI化に対応する方法と問題点

まず前提として、アプリ自身が「高DPIに対応してますよ!」と宣言しないといけません。
この宣言方法は、2種類あり、マニフェストで宣言するか、
アプリ内で「SetProcessDPIAware」を呼び出す方法があります。
これらの宣言方法については、「SetProcessDPIAware function」に記載されています。

一見、上記の方法だけで対応できるなら簡単じゃないかと思えるかもしれません。
実際の問題点は、高DPI対応宣言後の処理となります。
具体的には、座標、サイズ、位置などについて、
高DPIを考慮した数値で設定する必要が出てきます。

これから作るソフトならまだよいですが、今まで作ったソフトで高DPI化させようとした場合、
ソースコード上の全ての位置やサイズ情報を書き直す必要があるのです。

現実的な解決策

実は、今までのソースコード書き直しせず、簡単に解決することが可能です。
それは、標準関数の置き換えです。

以下に、いくつかの標準関数を置き換えたモジュールをおきます。
高DPI対応用のモジュールを作成する
(このモジュールは、実際に私が作ったツールで利用しています。)

このように、標準関数を置き換えたモジュールを
ソースコードの最初でincludeすることで、
全コードが高DPI対応用の命令で実行させるということです。

おわりに

これで、高DPI対応に関する記事は終わりです。
ありがとうございました。

ちなみに、高DPI対応を試験する際の注意点として
ディスプレイの設定から、「拡大縮小とレイアウト」で「100%」から変更させるという方法があるのですが、
一旦、サインアウト・サインインをやり直す必要があります。

サインアウト・サインインをしないと、
GetDeviceCaps の HIGHDPI_LOGPIXELSX / HIGHDPI_LOGPIXELSY
で取得できる数値が96のままになってしまいます。
気が付かずに、すこしはまってしまいました……。

コメント

タイトルとURLをコピーしました