WPFアプリなどではコントロールのエッジがきれいに描画されないことがある。.NET 4で導入されたプロパティを使い、これを修正する方法を紹介する。
対象:.NET 4以降
UIコントロールのエッジがボケて表示されてしまって困ったことはないだろうか? あるいは、表示した画像のピクセルがボケて表示されたことはないだろうか? .NET 4のWPFからは、それを簡単に解決するプロパティが追加された。本稿ではその方法を解説する。
次の画像が、今回の問題の例だ(4倍に拡大している)。二つの図形を左右に描いているが、右側で問題が発生している。赤い枠線は1ピクセル幅、その内側に1ピクセル空けて緑色の矩形を描画しているのだが、右側ではボケてしまっている。
この現象は、プログラムの側で指定したピクセルとデバイスの実ピクセルが一致しないときに発生する。プログラムの側で小数点以下の端数が付いた座標を指定しても発生するし、システムが画面解像度によって描画を拡大/縮小する過程でも発生することがある。
上の例では、次のコードのようにわざと小数点以下の端数が付いた座標を指定している。しかし、意識していなくても、例えばグリッドを「*」指定で3分割したりすれば座標に端数が付いてしまうのである。
<StackPanel Orientation="Horizontal" >
<Border Width="32" Height="32" Margin="2"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderThickness="1" BorderBrush="Red">
<Border Width="28" Height="28" Background="Green" />
</Border>
<Border Width="32" Height="32" Margin="2.3"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderThickness="1" BorderBrush="Red">
<Border Width="28" Height="28" Background="Green" />
</Border>
</StackPanel>
上記の問題を解決するには、UseLayoutRoundingプロパティをtrueに設定すればよい(次のコードと画像)。
その設定は、トップレベルのGridコントロールで行うとよい。子要素で設定した場合、トップレベルからその子要素までの間で座標計算に端数が出ていると、やはりボケてしまうからだ。
<Window ……省略……
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="rootGrid" UseLayoutRounding="True">
……省略……
なお、.NET 4以前の場合はUseLayoutRoundingプロパティがないので、代わりにSnapsToDevicePixelsプロパティを利用する。ただし、SnapsToDevicePixelsプロパティはUIコントロールの位置決めを実ピクセルに合わせるだけなので、DrawingContextを使って直接描画する場合や画像の内部などには効果がない。
また、WindowsストアアプリやUWPアプリで使うWindows Runtimeでは、UseLayoutRoundingプロパティの既定値はtrueに変更されているため、基本的にはこの問題は生じない*1。
*1 generic.xamlでUseLayoutRoundingプロパティがfalseに設定されている箇所があるので注意が必要だ。UWPでも、ラジオボタンの円やチェックボックスの四角などがfalseになっている。
描画位置を実ピクセルに合わせるにはUseLayoutRoundingプロパティをtrueに設定する。ただし、このプロパティをサポートしているのは.NET 4からなので注意してほしい。
利用可能バージョン:.NET Framework 4以降
カテゴリ:WPF/XAML 処理対象:コントロール
使用ライブラリ:FrameworkElementクラス(System.Windows名前空間)
Copyright© Digital Advantage Corp. All Rights Reserved.