午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

EdgeModeでアンチエイリアスの有無を切り替え、WPF

 
RenderOptions.SetEdgeModeで図形のアンチエイリアスの有無を切り替え
イメージ 1
左右それぞれのStackPanelの下の方に表示している図形は上から
Line(太さ0.5)
Line(太さ1.0)
Line(太さ5.0)Lineはそれぞれ2本ずつ
Rectangle
Ellipse
右のすべての図形は図形自体のEdgeModeにAliasedを指定している
左は指定なし
この状態からボタンでStackPanelのEdgeModeを切り替えてしている
 
EdgeMode
指定できるのは2種類でUnspecifiedとAliased
Unspecifiedは日本語で未定義、不特定の意味らしい
特に指定しない場合はこれになるみたいで結果はアンチエイリアスが有効な状態
Aliasedを指定するとアンチエイリアスが無効になる
親要素にAliasedを指定すると所属している子要素すべてもアンチエイリアス無効になる
 
UseLayoutRounding
これはおまけで試してみた、切り替えると表示位置が微妙に移動する
有効にすると表示位置をピクセルに合わせてくれる感じなのかなあ、よくわからん
 
SnapsToDevicePixels
切り替えても何も変化しないねえ
 
 
 
今回のVBコード
Class MainWindow
    Private MyRect As Path

    Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
       'Mode変更のボタン追加
        Call AddEdgeModeButton(MyStackP1)
        Call AddEdgeModeButton(MyStackP2)
        Call AddUselayoutRoundingButton(MyStackP1)
        Call AddUselayoutRoundingButton(MyStackP2)
        Call AddSnapsToDevicePixelsButton(MyStackP1)
        Call AddSnapsToDevicePixelsButton(MyStackP2)
       'Mode表示用のTextBlock追加
        Call AddTextBlock(MyStackP1)
        Call AddTextBlock(MyStackP2)

       'EdgeMode = Unspecified(初期設定)のLineを左のStackPanelに追加
        With MyStackP1.Children
            .Add(CreateLine(0.5, False)) '数値は線の太さ
            .Add(CreateLine(0.5, False))
            .Add(CreateLine(1.0, False))
            .Add(CreateLine(1.0, False))
            .Add(CreateLine(5.0, False))
            .Add(CreateLine(5.0, False))
            .Add(CreateRectangle(False))
            .Add(CreateEllipse(False))
        End With

       'EdgeMode = AliasedのLineを右のStackPanelに追加
        With MyStackP2.Children
            .Add(CreateLine(0.5, True))
            .Add(CreateLine(0.5, True))
            .Add(CreateLine(1.0, True))
            .Add(CreateLine(1.0, True))
            .Add(CreateLine(5.0, True))
            .Add(CreateLine(5.0, True))
            .Add(CreateRectangle(True))
            .Add(CreateEllipse(True))
        End With

    End Sub

   '図形作成
   'Line作成
    Private Function CreateLine(bold As Double, a As Boolean) As Line
        Dim l As New Line
        With l
            .Stroke = Brushes.Black
            .StrokeThickness = bold
            .X1 = 0 : .X2 = 150 : .Y1 = 0 : .Y2 = 10
        End With
        If a Then
            RenderOptions.SetEdgeMode(l, EdgeMode.Aliased)
        End If
        Return l
    End Function
   'Rectangle
    Private Function CreateRectangle(a As Boolean) As Rectangle
        Dim r As New Rectangle With {.Width = 50, .Height = 50,
            .Fill = Brushes.Black}
        If a Then RenderOptions.SetEdgeMode(r, EdgeMode.Aliased)
        Return r
    End Function
   'Ellipse
    Private Function CreateEllipse(a As Boolean) As Ellipse
        Dim el As New Ellipse With {.Width = 50, .Height = 50,
            .Fill = Brushes.Black}
        If a Then RenderOptions.SetEdgeMode(el, EdgeMode.Aliased)
        Return el
    End Function

   'ボタン作成
   'EdgeMode切り替えボタン作成
    Private Sub AddEdgeModeButton(p As StackPanel)
        Dim b As New Button With {.Content = "EdgeMode変更",
            .Margin = New Thickness(2)}
        p.Children.Add(b)
       'ボタンクリックイベントにくっつける
        AddHandler b.Click, AddressOf ChangeEdgeMode
    End Sub
   'UseLayoutRounding変更ボタン作成
    Private Sub AddUselayoutRoundingButton(p As StackPanel)
        Dim b As New Button With {.Content = "UseLayoutRounding変更",
            .Margin = New Thickness(2)}
        p.Children.Add(b)
        AddHandler b.Click, AddressOf ChangeUseLayoutRounding
    End Sub
   'SnapsToDevicePixels変更ボタン作成
    Private Sub AddSnapsToDevicePixelsButton(p As StackPanel)
        Dim b As New Button With {.Content = "SnapsToDevicePixels変更",
            .Margin = New Thickness(2)}
        p.Children.Add(b)
        AddHandler b.Click, AddressOf ChangeSnapsToDevicePixels
    End Sub


   'ボタンクリックイベント用
   '親パネルのRenderOptions.EdgeModeを切り替える
    Private Sub ChangeEdgeMode(sender As Object, e As RoutedEventArgs)
        Dim p As StackPanel = DirectCast(sender.parent, StackPanel)
        If RenderOptions.GetEdgeMode(p) = EdgeMode.Aliased Then
            RenderOptions.SetEdgeMode(p, EdgeMode.Unspecified)
        Else
            RenderOptions.SetEdgeMode(p, EdgeMode.Aliased)
        End If
    End Sub
   '親パネルのUseLayoutRoundingを切り替える
    Private Sub ChangeUseLayoutRounding(sender As Object, e As RoutedEventArgs)
        Dim p As StackPanel = DirectCast(sender.parent, StackPanel)
        p.UseLayoutRounding = Not p.UseLayoutRounding
    End Sub
   '親パネルのSnapsToDevicePixelsを切り替える
    Private Sub ChangeSnapsToDevicePixels(sender As Object, e As RoutedEventArgs)
        Dim p As StackPanel = DirectCast(sender.parent, StackPanel)
        p.SnapsToDevicePixels = Not p.SnapsToDevicePixels
    End Sub



    

   'Mode表示用TextBlock作成
    Private Sub AddTextBlock(p As StackPanel)
       'Bindingソース作成、StackPanelのEdgeModePropertyをソースにする
        Dim b As New Binding With {
            .Source = p,
            .Path = New PropertyPath(RenderOptions.EdgeModeProperty),
            .StringFormat = "PanelのEdgeMode = {0}"
        }

        Dim tb As New TextBlock
       'TextBlockのTextPropertyにBinding
        tb.SetBinding(TextBlock.TextProperty, b)
        p.Children.Add(tb)

       'UseLayoutRounding表示用TextBlock
        tb = New TextBlock
        b = New Binding With {
            .Source = p,
            .Path = New PropertyPath(StackPanel.UseLayoutRoundingProperty),
            .StringFormat = "PanelのUseLayoutRounding = {0}"}
        tb.SetBinding(TextBlock.TextProperty, b)
        p.Children.Add(tb)

       'SnapToDevicePixels表示用TextBlock
        tb = New TextBlock
        b = New Binding With {
            .Source = p,
            .Path = New PropertyPath(StackPanel.SnapsToDevicePixelsProperty),
            .StringFormat = "PanelのSnapToDevicePixels = {0}"}
        tb.SetBinding(TextBlock.TextProperty, b)
        p.Children.Add(tb)
    End Sub
End Class
 
 
XAMLデザインモード

f:id:gogowaten:20191031123845p:plain

 
 
参照したところ
 
WPFアンチエイリアシングを無効にする方法 – 川西 裕幸のブログ
https://blogs.msdn.microsoft.com/hiroyuk/2009/02/15/wpf-2/

WPFでのUIアンチエイリアス封じ込め - コンクリートアスパラガス
http://d.hatena.ne.jp/Conpara02/20120526/1338017590

MahAppsのTreeViewをWPFで使ったときの話 - PG日誌
http://takachan.hatenablog.com/entry/2016/01/06/231255

WPF】グリッド状の模様を描く (1)~(6)のまとめ – ザワプロ!
http://zawapro.com/?p=1041

.NET TIPS: WPF/ UWP: コントロールのエッジをシャープに描画するには?[XAML] - @IT
http://www.atmarkit.co.jp/ait/articles/1602/17/news034.html

文字列をフォーマットして表示するはなし with 多言語対応とかマークアップ拡張とか - Qiita
http://qiita.com/wonderful_panda/items/a45ffaaca7f9c6e0d494
ありがとうございます!
 
 
 
この前の記事の
WPF、BindingのStringFormat、数値の書式設定をVBコードで ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/14895536.html
これに付け足し
 
TextBlockにBindingする値が文字列でその文字列に別の文字列を追加して表示したいとき
今回のだとこれ、EdgeModeをTextBlockにBindingして表示する
'Bindingソース作成、StackPanelのEdgeModePropertyをソースにする
Dim b As New Binding With {
.Source = p,
.Path = New PropertyPath(RenderOptions.EdgeModeProperty),
.StringFormat = "PanelのEdgeMode = {0}"
}
EdgeModeがAliasedのとき
BindingのStringFormatに何も指定しないと表示されるのはAliased
PanelのEdgeMode  = Aliasedって表示したいときは上のように
.StringFormat = "PanelのEdgeMode = {0}"
って書けばいいみたい、{0}ってところにBindingした値が表示される
 
 
次のVB.NETWPFの記事
画像をくっきり表示させたい(ぼやけるのがイヤな)とき、EdgeModeとScalingMode、WPF ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/14912530.html