HAHAHA。なんでなんやろ,歴史調べたら人々が奮闘してきたのがわかる。
1. この原因を調べるきっかけ。
これ。
結論から言うと解決の道筋は見えました(まだ綺麗に実装し直していない)。
2. 人々の歴史。
MetroRadiance もそうですが,100% 環境で最大化した場合,外側に 8epx 引っ張られるので,それを補正する xaml。
<Trigger Property="WindowState" Value="Maximized"> <Setter Property="BorderThickness" Value="0" /> <Setter Property="Padding" Value="8" /> </Trigger>
これ,100% 環境でだけ動作するコードなんですよね (100% 以外は余白の大きさが違う)。そしたらやっぱり気になるじゃないですか,回避方法。
2.1 回避方法 1: ハードコード
currentDpi を取得して margin を決め打ちするハードコード! すばらしいですね,調査する根気。
protected virtual Thickness GetDefaultMarginForDpi() { int currentDPI = SystemHelper.GetCurrentDPI(); Thickness thickness = new Thickness(8, 8, 8, 8); if (currentDPI == 120) { thickness = new Thickness(7, 7, 4, 5); } else if (currentDPI == 144) { thickness = new Thickness(7, 7, 3, 1); } else if (currentDPI == 168) { thickness = new Thickness(6, 6, 2, 0); } else if (currentDPI == 192) { thickness = new Thickness(6, 6, 0, 0); } else if (currentDPI == 240) { thickness = new Thickness(6, 6, 0, 0); } return thickness; }
いやほんとすごいですね。気づいてない不具合だったので,気づけただけでもすごいと思います。
2.2 回避方法 2: インテリジェンス
すばらしいです。模範解答です。
これで! OK かと思いきや…… ですよね。
3. やっぱり自動で隠れるタスク バーがひらけない。
そこで気づいちゃったんですね。感の良い人なら知っているかもしれません。
以下は 200% で動かしている Visual Studio の最大化ウィンドウの左下部分です (100% ととはちょっと違います)。
え? どこがどう違うって?
はい,普通だとその反応が正解ですね。実は,タスクバーが下に設定されている場合,下に 1epx (200% なので 2px) の余白があります。つまり,2.2 で提示した最大化の範囲指定にちょっと手を加えて,自動でタスク バーが隠れる場合,タスクバーのある方向に 1epx の余白を追加してやれば良いんです。
8/1 12:43追記: 1epx ではなく,2px かもしれません。スケーリングにかかわらず (要調査)。
動きました
まとめ
WPF のカスタムウィンドウ最大化問題の解決方法は:
WM_GETMINMAXINFO
で正しい最大化情報を指定する。- その際,タスク バーが自動で隠れる設定である場合,補正をかけてやる。
これが正解でした。誰がわかるねんこんなん……
8/2 追記: 実はこの方法,大きな問題がありまして……
タスクバーの移動に対応できない/(^o^)\
ということで新しい記事書いてます。
おまけ
ここからは興味ある人向けの話題。
WPF はすでにオープンソースで開発されていますが,WM_GETMINMAXINFO
周りの挙動を追ってみました。
他にも WM_GETMINMAXINFO
を操作する部分があるかもしれませんが,特に変なことしていないと言うことなので,OS からの挙動っぽいですねこれ。