Windowsでゲームのランチャーを起動したところ、ウィンドウが妙に大きく表示されることがあった。
別のときには、2台のモニターのちょうど境界付近にウィンドウが出てきた。一方で、普通に表示されるアプリも多い。前回のウィンドウ位置を記憶しているアプリや、メインディスプレイ上へ素直に出てくるアプリは正常に動いていた。
私の環境は次のようになっている。
| 項目 | 構成 |
|---|---|
| OS | Windows |
| メインディスプレイ | FHD |
| サブディスプレイ | 4K |
| 構成 | デュアルディスプレイ |
| 症状 | 一部のアプリだけ巨大表示、または2画面の境界付近に表示 |
結論から書くと、問題が出るアプリの「高DPIスケール設定の上書き」を アプリケーション に変更したところ、次回起動時から通常の大きさになり、ウィンドウも先ほど使っていた位置へ表示されるようになった。
高DPIスケール設定を「アプリケーション」にしたら直った
今回は、問題が起きているアプリだけに互換性設定を追加した。Windows全体のディスプレイ設定はそのままにしている。
私の環境では、次の手順で変更できた。
- アプリのショートカットを右クリックして「プロパティ」を開く
- 「互換性」タブを開く
- 「高DPI設定の変更」を開く
- 「高DPIスケール設定の上書き」を有効にする
- 「拡大縮小の実行元」を「アプリケーション」にする
- アプリを終了して起動し直す
変更後に起動すると、巨大化していたウィンドウは普通の大きさになった。2画面の境界付近へ出ていた位置も戻り、直前に使っていた場所へ表示された。
高DPIスケール設定を変えただけでサイズと位置の両方が正常になったため、DPIスケーリング周辺を確認する方向は合っていた。
問題のポイントは解像度差だけでなくDPIスケーリング
最初は単純に「4KとFHDを混ぜているからだろう」と考えた。
Windowsでアプリの表示サイズには、解像度に加えて、モニターごとの表示スケールとアプリ側のDPI処理が関係する。今回確認できているのはFHDと4Kを組み合わせた構成までで、各モニターの表示スケール値は記録していない。
Windowsではモニターごとにスケールを設定できる。さらにデスクトップアプリ側には、DPIをどこまで自分で扱うかを示すDPI Awarenessという仕組みがある。
Microsoftの資料では、主に次のようなモードが説明されている。
| DPI Awareness | おおまかな動作 |
|---|---|
| DPI Unaware | 96 DPIを前提に描画し、必要に応じてWindowsが拡大する |
| System DPI Aware | システム側のDPIを基準にし、別のDPIへ移動した場合はWindowsが拡大縮小する |
| Per-Monitor DPI Aware | ウィンドウがあるモニターのDPIを認識し、変更時の調整をアプリ側で行う |
| Per-Monitor V2 | Per-Monitorを拡張し、ウィンドウやダイアログなどのDPI変更対応が改善されている |
Microsoftは、異なるスケールのディスプレイ間を移動するデスクトップアプリではPer-Monitor DPI Awarenessへの対応を推奨している。
High DPI Desktop Application Development on Windows - Win32 apps
This content is targeted at developers who are looking to update desktop applications to handle dynamic display scale factor (a.k.a.
https://learn.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
DPI_AWARENESS_CONTEXT handle (windef.h) - Win32 apps
Identifies the awareness context for a window.
https://learn.microsoft.com/en-us/windows/win32/hidpi/dpi-awareness-context
DPIの扱いはアプリごとに異なる。
古いWin32アプリもあれば、独自UIのアプリもある。ChromiumやWebViewを使うデスクトップアプリもあり、フレームワーク側の実装やアプリ自身の設定によって挙動が変わる。
そのため、同じPCで同じモニター構成を使っていても、
- あるアプリはそのまま正常に表示される
- あるアプリは4K側へ移動すると大きさが変わる
- あるアプリは起動時だけ表示サイズがおかしい
- あるアプリはウィンドウ位置までずれる
という差が出る。
今回も症状は一部のアプリに限られていた。
FHDをメインディスプレイにしていても起こった
私の環境ではFHD側をメインディスプレイにしている。普段使うアプリの多くはFHD側に起動し、前回の位置を記憶しているアプリも基本的にはその場所へ戻ってくる。
そのため、最初はサブの4Kディスプレイが今回の症状に関係しているとは考えにくかった。
実際には、ウィンドウをどのモニター基準で配置するか、保存した座標をどう復元するか、DPI変更をどう扱うかはアプリの実装にも左右される。FHDをメインにしていることだけでは、今回のような表示崩れは避けられなかった。
2台のモニターの境界に出ることもあった
もう一つ起きていたのが、ウィンドウが2台のモニターの境界付近に出る現象だった。
Windowsでは複数のモニター全体を囲む領域を仮想画面として扱う。Microsoftの資料にも、仮想画面を基準に中央配置すると仮想画面全体の中央へ出る例がある。
Positioning Objects on Multiple Display Monitors - Win32 apps
A window or menu that is on more than one monitor causes visual disruption for a viewer. To minimize this problem, the system displays menus and new and maximized windows on one monitor. The following table shows how the monitor is chosen.
https://learn.microsoft.com/en-us/windows/win32/gdi/positioning-objects-on-multiple-display-monitors
Windowsにはモニター単位とは別に仮想画面の座標系がある。今回のアプリがどの配置方法を使っていたかまでは追っていない。
実際に確認できたのは、高DPI設定を「アプリケーション」へ変更すると、巨大表示だけでなく位置ずれも同時に直ったことだ。
高DPIの設定はアプリごとに選ぶ
今回のアプリでは「アプリケーション」で改善したが、別のアプリでは適する設定が変わる。
高DPIスケール設定の上書きには、環境によって次の選択肢が表示される。
- アプリケーション
- システム
- システム(拡張)
どれが合うかはアプリの実装によって変わる。
「アプリケーション」を選ぶと、Windows側のDPIスケーリング介入を抑え、アプリ側に処理させる方向になる。ここで変わるのはWindows側のスケーリングの扱いで、アプリ自身のDPI実装はそのまま使われる。
逆に、DPI対応が弱い古いアプリでは「システム」や「システム(拡張)」のほうが見やすくなることもある。
そのため、私はWindows全体を変更せず、症状が出るアプリだけ個別に設定することにした。
更新でexeが変わるアプリなので、ショートカットから設定した
今回のアプリは、アップデートすると実体のexeが別の場所や別バージョンへ切り替わるタイプだった。
そこで、普段使っているショートカットのプロパティから高DPI設定を変更した。
今回の起動方法では、この設定で正常に動いている。
Windowsの互換性設定は実行ファイルのパスに紐づいて保持されることがある。更新で実体のexeやそのパスが変わると、互換性設定の対象も変わる場合がある。
再び巨大表示されるようになったら、最初に高DPI設定がまだ効いているかを確認するつもりだ。
モニター構成を変える前に、高DPI設定を試してよかった
最初は、4KとFHDを組み合わせている以上、メインディスプレイや解像度、表示スケール側を調整する必要があるのかと思っていた。
今回はそこまで触らず、問題が出ているアプリだけ高DPIスケール設定を「アプリケーション」に変更することで解決した。FHDと4Kのデュアルディスプレイ構成もそのまま使えている。
同じように、一部のアプリだけ巨大に表示されたり、別のモニター側へずれたりする場合は、ディスプレイ全体の設定を変える前に、そのアプリの高DPI設定を確認してみる価値がある。