【入門編】Windows FormsにおけるDPI変更動的検知:DynamicDPI対応でモニター移動時のレイアウト崩れとフォント滲みを完全に防止する – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

こんにちは!Windows Formsアプリの開発、順調に進んでいますか?

「作ったアプリを4KモニターからノートPCの画面に移動したら、文字がボヤけたり、ボタンが画面からはみ出したりしてカッコ悪い……」
そんなレイアウト崩れの悩みに直面したことはありませんか?

近年の高解像度(4KやRetinaなど)ディスプレイの普及により、Windowsアプリ開発において「DPI(ドット抜けのない美しい描画を保つための倍率設定)」の制御は避けて通れない重要課題です。特に、アプリを起動したまま別のモニターへ「よいしょ」とドラッグして移動させたとき、古い設計のままだとレイアウトが盛大に崩れてしまいます。

今回は、VB.NETのWindows Formsにおいて、この「動的なDPI変更(Dynamic DPI)」を完璧に検知し、モニターをまたいでもレイアウト崩れやフォントの滲みをゼロにする極意を伝授します。

ここをクリアすれば、あなたのアプリは見違えるほどプロフェッショナルな動きをするようになりますよ。さあ、一緒に本質を学んでいきましょう!

—

なぜモニターを移動するとレイアウトが崩れるのか?

Windows Formsの歴史は長く、その根底には「画面の解像度は一定である」という古い前提がありました。
何も対策をしないと、OSはアプリを最初に起動したモニターのDPI(例えば100%)で固定してしまいます。それをDPI 200%の超高精細モニターに移動させると、OSが無理やり拡大(ビットマップ引き延ばし)するため、フォントが盛大に滲み、コントロールの配置がズタズタになるという悲劇が起きます。

これを解決するのが、Windows 10/11世代のOSが提供する `PerMonitorV2` というアーキテクチャと、VB.NET側での動的なイベントフックです。

—

解決へのアプローチ:動的DPI変更の全体像

VB.NETでこれを実現するには、以下の2つのステップを踏みます。

1. アプリ(またはフォーム)に「私、動的DPIに対応します」と宣言させる。
2. モニター移動の瞬間(DPI変更イベント)をキャッチし、コントロールの再スケーリングを制御する。

言葉で言うのは簡単ですが、Windows Formsのデフォルトの挙動は少し気まぐれです。完璧な制御を行うための実用コードを見ていきましょう。

—

実装コード:DynamicDPI完全対応フォーム

以下のコードは、Visual Basic (VB.NET) のWindows Formsでそのままコピペして使える、実践的なフォームクラスのテンプレートです。

Public Class DynamicDpiForm

‘ フォームのコンストラクタ、または Load イベント
Private Sub DynamicDpiForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
‘ ここで初期設定や、動的スケーリングのログなどを仕込むことも可能です
Me.Text = “Dynamic DPI 対応フォーム (PerMonitorV2)”
End Sub

”’

”’ Windowsから「おい、DPIが変わったぞ!」と通知される極めて重要なイベント
”’

Protected Overrides Sub OnDpiChanged(e: DpiChangedEventArgs)
MyBase.OnDpiChanged(e)

‘ 【プロの知見】
‘ ここでデバッグ出力や、独自のレイアウト再計算を挟むことができます。
‘ e.DeviceDpiOld から e.DeviceDpiNew へ倍率が変化したことが取得可能です。
System.Diagnostics.Debug.WriteLine($”DPI変更検知: {e.DeviceDpiOld} -> {e.DeviceDpiNew}”)

‘ ※Windows Formsの標準機能が自動でコントロールのスケール調整を行いますが、
‘ 複雑な独自描画やカスタムコントロールがある場合は、このメソッド内で再描画を強制します。
Me.Invalidate(True)
End Sub

”’

”’ フォントやタイトルのスケール変更が必要なタイミングで呼ばれるオーバーライド
”’

Protected Overrides Sub ScaleControl(factor As SizeF, specified As BoundsSpecified)
MyBase.ScaleControl(factor, specified)

‘ ここに「フォントサイズが急激に変わった時に特定のレイアウトを微調整する」といった
‘ 現場特有のハックを記述できます。
End Sub

End Class

—

現場で絶対に知っておくべき「落とし穴」と極意

上記のコードを書くだけでなく、Windows Formsアプリ全体の「Manifest(マニフェスト)」設定を正しく行わないと、そもそもOSから動的DPIの通知が来ません。ここが初学者が最もハマりやすいポイントです。

1. `app.manifest` の設定を確認する

プロジェクトのプロパティ、または `app.manifest` ファイルを開き、High DPIに対応しているか確認してください。以下の記述が命綱となります。





PerMonitorV2, PerMonitor
true

もしここが古い設定(`System` DPIなど)になっていると、どんなにVB.NET側で頑張ってイベントを書いても、モニターを移動した瞬間に画面全体がボヤけてしまいます。必ず `PerMonitorV2` を指定しましょう。

2. 外部ライブラリや古いコントロールの呪縛

もしアプリ内でサードパーティ製の古いUIコントロールを使っている場合、そいつらが自動スケーリングについてこれず、レイアウトが崩れる原因になります。
可能な限り、標準のコントロール(`TableLayoutPanel` や `FlowLayoutPanel` など)を活用し、座標をハードコーディングする(例:`Button1.Left = 150` のように直書きする)悪しき習慣は捨て去りましょう。レイアウトはコンテナに任せるのがモダンな鉄則です。

—

まとめ

今回は、Windows FormsにおけるDynamic DPI対応について、プロのアーキテクチャ視点から解説しました。

  • モニター移動時の崩れと滲みの原因は、OSの古いスケーリング強制にある。
  • `app.manifest` で `PerMonitorV2` を有効化し、OSから正しく通知を受け取る。
  • `OnDpiChanged` をオーバーライドして、必要に応じてカスタムの再描画や調整を行う。

ここをしっかりとクリアしておけば、「高解像度モニターに対応していない使えないアプリ」という評価を完全に回避できます。ユーザーが感動するような、滑らかで美しいデスクトップアプリを一緒に作り上げていきましょう!

Visual Basicの基本をマスターしたあなたなら、もう次のステップへ進む実力は十分です。明日からの開発に、ぜひこの知見を取り入れてみてくださいね。

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