single.php

C# WinUI 3アプリでディスプレイの拡大率を取得する手順

C# WinUI 3アプリを作っていく途中で、躓いた部分を備忘録的に投稿します。今回はアンパッケージ化したプロジェクトでフォームのサイズを位置をXML形式で保存する手順です。

MoveAndResizeで差異が発生

C#のWinUI 3プロジェクトでメインウィンドウなどのサイズ変更をするMoveAndResizeメソッドに幅や高さなどの値を入れると、ディスプレイの拡大率によって差異が生まれます。

4Kモニターを利用していると、[システム|ディスプレイ]設定で自動的に推奨値である150%が設定されます。

MoveAndResizeに変更したい幅と高さのサイズを入力した場合、拡大縮小の値が[100%]の場合は想定したサイズに変更されますが、[150%]の場合にはサイズが大きく表示されます。

Win32で解像度を取得して調整

色々試してみましたが、アンパッケージ化したWinUI3プロジェクトの場合、制約が多くてWin32のGetDpiForWindow(User32.dll)を使うことで拡大率に合わせてサイズ変更をすることができました。

具体的には次の処理を追加します。

まずはクラス内の先頭にWin32を利用するおまじない。

[DllImport("user32.dll")]
static extern int GetDpiForWindow(IntPtr hWnd);

これでGetDpiForWindowが使えるようになります。

次にウィンドウのハンドルを使ってGetDpiForWindowを通して解像度(DPI)を取得します。

IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
double dpi = GetDpiForWindow(hWnd);

取得された値から、拡大/縮小で設定されている値が分かります。

GetDpiForWindowの戻り値拡大/縮小の設定値
96100%
120125%
144150%
192200%

注意するのは、ウィンドウが表示されている状態でGetDpiForWindowを利用する必要があり、非表示の状態では正しい解像度が取得できません。

例えば、WindowのActivatedイベントなどで取得する必要があります。

後は取得された解像度を使って、幅や高さのサイズ調整(コード内の dpi / 96 の部分)を行います。

private void MoveAndResizeWindow()
{
  int nWidth = 640;
  int nHeight = 360;
  int nTop = 0;
  int nLeft = 0;

  IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
  double dpi = GetDpiForWindow(hWnd);

  nWidth = nWidth * (int)(dpi / 96);
  nHeight = nHeight * (int)(dpi / 96);

  Windows.Graphics.RectInt32 rect = new Windows.Graphics.RectInt32(nLeft, nTop, nWidth, nHeight);

  Microsoft.UI.WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
  Microsoft.UI.Windowing.AppWindow AppWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);

  AppWindow.MoveAndResize(rect);
}

実行するとディスプレイの[拡大/縮小]設定に応じて画面のサイズが変更されるようになります。

まとめ

今回は、WinUI 3 アプリのウィンドウのサイズをディスプレイの拡大率に応じて変更する方法を書きました。

Windows11/10では4Kモニターなどの高解像度のディスプレイで[システム|ディスプレイ]の[拡大/縮小]が150%に自動設定されます。

そのために、MoveAndResizeメソッドなどを使ってウィンドウのサイズ変更をした場合に100%の拡大率が設定されているディスプレイよりも大きく変更されるようになります。

GetDpiForWindow で実際の解像度を取得して調整することで正しいサイズに変更ができます。

C#のWinUI 3アプリでMoveAndResizeメソッドで変更したサイズがディスプレイによって違う場合の参考になれば幸いです。

スポンサーリンク

最後までご覧いただき、ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です