高DPIの有効化設定
Delphi/400 10 Seattle以降では、
プロジェクトオプションで高DPIの有効化がサポートされています。
高DPIを有効にすると、Windowsのディスプレイの設定における
拡大縮小の設定(テキスト、アプリ、その他の項目のサイズを変更する)に対応します。
ディスプレイの拡大縮小が100%でない場合に、フォームやその中の項目のサイズが自動拡張されます。
それぞれ、以下の設定で有効化が可能です。
- 10 Seattle / 10.2 Tokyo
- アプリケーション → マニフェストファイル → 「高 DPI の有効化」をチェックオン
(デフォルトは有効になっています)
- アプリケーション → マニフェストファイル → 「高 DPI の有効化」をチェックオン
- 11 Alexandria / 12 Athens
- アプリケーション → マニフェスト → 「DPI の認識」の各項目値を設定
- 各項目の設定値について:
- [なし]: DPI 認識なし。
- [対応せず]: 100%スケーリング(96 DPI)を想定してアプリケーションをレンダリングします。
- [システム DPI に対応]: PCログイン時にメイン ディスプレイのアプリケーション API が分かっている場合に選択します。
- [ディスプレイごとの DPI に対応]: アプリケーションが異なる DPI を持つモニター間を移動する際に、随時 DPI スケーリングを変更させる場合に選択します。
- [ディスプレイごとの DPI に対応 V2]: 初期値。アプリケーション DPI が変わる際に通知を受け取りたい場合に選択します。
- [GDI スケーリング]: どのディスプレイに表示されているかに関係なく、グラフィックとテキストを正しいスケールでレンダリングする場合に選択します。
例えば、ある画面でディスプレイの拡大縮小の設定が
通常(100%)の場合と150%の場合では、このように見た目の差が生じ、
細かい文字が見えにくい方でも見やすくなります。
(TImage内の画像など、拡大されない項目も一部存在します。)
クリックして拡大表示してみて下さい
代替手段で拡大(または縮小)する
Delphi/400 XE7以前のバージョンをご利用の場合や、
何らかの理由で高DPIを有効にすることができない場合は、
代替として以下の方法で設定することも可能です。
対象フォームに対して「ScaleBy」メソッドを実行することで、
スケーリングを変更して見た目の大きさを変更できます。縮小も可能です。
この方法であれば、ユーザーの中で希望者だけが拡大(縮小)できるような記述が可能です。
また特定画面のみを常に拡大(縮小)させたい場合には、FormCreateで記述することも可能です。
<例>
// フォームを150%にスケーリング
Self.ScaleBy(3, 2);
※「第1引数÷第2引数」の倍率になります。「3, 2」と指定した場合は150%になります。
※複数回実行した場合、拡大縮小した倍率からさらに拡大縮小が行われます。
そのため、意図せず複数回走ることがないよう記述場所にご注意ください。
高DPIと比較しても見た目の差はほとんど無い
画面拡大(縮小)時における注意点
先述の通り、TImage内の画像など、一部の項目は拡大されません。
また、拡大縮小を行っていても画面内の座標は変わらないため
Height・WidthやTop・Leftを使用している画面では注意が必要です。
例えば下図のように、
SpeedButton1.Top := 60;
SpeedButton1.Left := 60;
というロジックがあった場合、
元々の(拡大縮小を無視した)指定ピクセルの位置にTopやLeftが設定されてしまいます。
こちらの解決にあたっては、
以下の2通りのいずれかをご検討ください。
1.高DPI非対応の設定を固定させる(11 Alexandria~)
高DPIの認識を[対応せず]に設定することで、
固定で100%スケーリングを想定してアプリケーションをレンダリングします。
これによって、高DPIの画面でもデフォルトのTopやLeftが設定されます。
(※ただし、100%スケーリングのため高DPIでは文字が少々ぼやけます。)
(※フォームのScaleByメソッドで拡大している場合は効きません。)
2.ロジックで倍率を計算する
「GetDeviceCaps」というWindows API 関数を使用することで、
プライマリモニターの「テキスト、アプリ、その他の項目のサイズ」を取得することができます。
ここで取得した倍率を掛け算してTopやLeftにセットすることで、
想定の位置に設定ができるようになります。
(※複数モニター使用で、倍率が異なる場合も、プライマリモニターの設定値が取得されます。)
(※フォームのScaleByメソッドで拡大した場合は、ScaleByで拡大した倍率を使用します。)
<ロジック例>
{*******************************************************************************
目的: 「テキスト、アプリ、その他の項目のサイズ」の倍率取得(※共通関数化)
引数:
戻値: 倍率(小数で、100%のときは1を返す)
*******************************************************************************}
function GetSizeOfTextAppsAndOtherItems: Currency; // ※関数の名前は任意
var
iDPI_X: Integer;
begin
// プライマリモニターの「テキスト、アプリ、その他の項目のサイズ」を取得
iDPI_X := GetDeviceCaps(GetDC(0), LOGPIXELSX);
// 100%=96dpiに対する倍率を返す
Result := iDPI_X / 96;
end;
{*******************************************************************************
目的: ボタン押下時処理(高DPI設定の場合)
引数:
戻値:
*******************************************************************************}
procedure TForm1.Button1Click(Sender: TObject);
begin
// 取得した倍率を、設定したいTopやLeftに掛け算する
SpeedButton1.Top := Trunc(60 * GetSizeOfTextAppsAndOtherItems);
SpeedButton1.Left := Trunc(60 * GetSizeOfTextAppsAndOtherItems);
end;
{*******************************************************************************
目的: ボタン押下時処理(ScaleByを使用した場合)
引数:
戻値:
*******************************************************************************}
procedure TForm1.Button1Click(Sender: TObject);
begin
// ScaleByで拡大した倍率を直接掛け算する
//(ここでは前項の『Self.ScaleBy(3, 2);』した場合を想定)
SpeedButton1.Top := Trunc(60 * (3 / 2));
SpeedButton1.Left := Trunc(60 * (3 / 2));
end;
<関連リンク>