2015/11/14

WPFのPer-Monitor DPIサポート(その1)

WPF自体のPer-Monitor DPIサポートについて。


従来、WPF自体にはPer-Monitor DPIのサポートはなく、Win32 APIを駆使する必要があったわけですが、.NET Framework 4.6.1の後のバージョンでようやくサポートが入るようです。
このエントリ中にあるサーベイに登録すればプレビュー版を試せるとのことで、登録しておいたところ、昨日招待メールが届いたのでダウンロードして試してみました。

ダウンロードできるのは.NET Framework 4.6.1のプレビュー版のようで、それを利用するサンプルコードは既にGitHubで公開されています。
このサンプルコードの範囲内で簡単にまとめると、以下が追加されています。
  • System.Windows名前空間
    • DpiScaleInfo構造体(DPI情報を格納する)

  • System.Windows.Media.VisualTreeHelperクラス
    • public static DpiScaleInfo GetDpi(Visual visual)メソッド
    • public static void SetRootDpi(Visual visual, DpiScaleInfo dpiInfo)メソッド

  • System.Windows.Windowクラス
    • protected override void OnDpiChanged(DpiScaleInfo oldDpiScaleInfo, DpiScaleInfo newDpiScaleInfo)メソッド

  • System.Windows.Controls.Imageクラス
    • protected override void OnDpiChanged(DpiScaleInfo oldDpiScaleInfo, DpiScaleInfo newDpiScaleInfo)メソッド
    • public event RoutedEventHandler DpiChangedイベントハンドラー
さらにコメントを見ると、大元のSystem.Windows.Media.VisualクラスにOnDpiChangedメソッドとDpiChangedイベントハンドラーが追加されるようです。

つまり、他の色々なイベント処理と同じように、各コントロールでDPI変化イベントを捉えて処理できるようになる、ということです。当然コントロールによって予め処理が作り込まれているものもあって、Windowクラスではモニターをまたがって移動したときに自動的にサイズ変更がされるようになっていました(位置はWM_DPICHANGED準拠)。さらに必要な処理があれば、OnDpiChangedをオーバーライドするなりDpiChangedに登録するなりして入れ込めばいいわけですね。

どんなものが来るのかなと思ってましたが、自然な拡張のようでとりあえず安心しました。

[追記1]

DpiChangedイベントハンドラーはRoutedEventHandlerとなっているとおり、引数はただのRoutedEventArgsなので、DPI情報を直接取得はできません。これは少しだけ面倒なので、以下のような専用のDpiChangedEventArgsを使うようにしてはどうかとフィードバックしてみました。

[追記2]

フィードバックへの返信で、このサポートが入るのは4.6.1ではなく、その後のバージョンだと訂正されたので、修正しました。

0 コメント :