【実務・中級編】Windows FormsのDPIスケーリングと高解像度ディスプレイ対応:4K環境でも文字やボタンがボケない・崩れないためのマニフェスト設定 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

Windows Formsの「ボケ」を根絶せよ:4K時代に負けないDPI対応の極意

業務自動化ツールを開発していると、いまだに「4Kモニターで表示するとUIが異常に小さくなる」「拡大表示するとフォントが滲む」という壁に突き当たることがあるだろう。これはOS側のDPIスケーリング設定と、古き良きWindows Formsのレンダリング方式が「噛み合っていない」ことに起因する。

多くの開発者が陥る罠は、設定をいじって「なんとなく表示されるようになった」で満足することだ。しかし、真のエンジニアはOSのライフサイクルを制御下に置く。今回は、Per-Monitor V2対応を見据えた、プロダクションレベルの「DPIボケ防止」の極意を伝授する。

1. マニフェスト設定:OSへの「宣戦布告」

Windows FormsアプリケーションがOSのスケーリングを正しく処理するためには、まず`app.manifest`で「私はDPIを認識している」とOSに明示する必要がある。これがないと、OSは無理やりアプリを拡大して「ボケ」を生み出す。

プロジェクトのプロパティからマニフェストファイルを追加し、以下の設定を記述せよ。





PerMonitorV2, PerMonitor
true

なぜ `PerMonitorV2` なのか?
旧来の `System` DPI設定では、メインモニターの解像度に引きずられてサブモニター側で表示が崩れる。`PerMonitorV2` はモニターごとのDPI変更を動的に検知し、フォームの再描画を正しく制御するための現代的なデファクトスタンダードだ。

2. コードレベルの防衛線:Program.csでの初期化

マニフェストを書いただけでは不十分だ。アプリケーションの開始地点(`Sub Main`)で、OSのレンダリング設定を明示的に有効化する必要がある。

Imports System.Windows.Forms

Friend NotInheritable Class Program

Friend Shared Sub Main()
‘ 高DPIサポートの有効化(必須)
‘ これを記述しないと、OSの仮想化レイヤーが働いてしまい、
‘ UIコントロールの座標計算にズレが生じる
If Environment.OSVersion.Version.Major >= 6 Then
SetProcessDPIAware()
End If

Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)

‘ スケールモードをDPIベースに設定する
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2)

Application.Run(New MainForm())
End Sub


Private Shared Function SetProcessDPIAware() As Boolean
End Function
End Class

3. 実務で「崩れない」ための設計原則

高解像度環境では、絶対座標(`Location = New Point(10, 10)`)でのUI配置は「死」を意味する。以下の原則を叩き込んでおけ。

  • AnchorとDockを信じろ: コントロールの固定には `Anchor` プロパティを駆使し、レイアウトが動的に変化する余地を残すこと。
  • TableLayoutPanelの積極活用: 行・列の割合でコンポーネントを管理せよ。これを使うだけで、DPI変化時のリサイズ処理が劇的に楽になる。
  • フォント指定の罠: `Me.Font = New Font(“Meiryo UI”, 9F)` のように、固定フォントを使う際は注意が必要だ。`SystemFonts.DefaultFont` を基点に相対的に設定することで、OS側のフォント設定との乖離を防げる。

4. データベース連携とパフォーマンスの注意点

UIのDPI対応と並行して、業務ツールで重要なのが「データ層との分離」だ。UIの描画処理がDPI変更によって再実行されるたびに、データベースへ再クエリを投げるような設計にしてはいけない。

アンチパターン:
`Form_Load` や `Resize` イベント内で直接 `SELECT` 文を発行する。

正しい設計(セパレーション・オブ・コンサーン):
1. データ取得層: `DataTable` や `List(Of T)` にデータを詰め込み、メモリ上にキャッシュする。
2. UI表示層: `BindingSource` を介してコントロールにバインドする。
3. DPI変更時: `OnDpiChanged` イベントで、必要であればレイアウト調整のみを行う。データ再取得は行わない。

最後に:エンジニアとしての矜持

「とりあえず動けばいい」というコードは、数年後に必ず自らの首を絞める。4Kディスプレイが当たり前になった今、DPI対応を後回しにするのは技術的負債以外の何物でもない。

今回提示した `PerMonitorV2` の実装と、レイアウトの流動化を徹底すれば、あなたの作る業務ツールはどんな環境でも「ボケない、崩れない、プロフェッショナルな挙動」を実現するはずだ。

コードを書き換える際は、常にその先の「誰がこのツールを保守するのか」を想像しろ。それが、伝説的な自動化エンジニアへの第一歩だ。健闘を祈る。

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