Search code examples
c#.netwpf

WPF Pixel line blurring


I'm creating a button style that contains a straight line:

    <Button VerticalAlignment="Center" HorizontalAlignment="Center">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Background" Value="#F0F0F0"/>
                <Setter Property="Width" Value="50"/>
                <Setter Property="Height" Value="50"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Grid Background="{TemplateBinding Background}">
                                <Path Stroke="Black" StrokeThickness="1" Data="M0,0 L10,0" 
                                      VerticalAlignment="Center" HorizontalAlignment="Center"
                                      SnapsToDevicePixels="True" UseLayoutRounding="True"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Button.Style>
    </Button>

But instead of a 1px wide line, I always get a 2px wide line:

enter image description here

I tried using the following (both in relation to the parent Grid and the Path element itself): UseLayoutRounding="True", SnapsToDevicePixels="True", RenderOptions.BitmapScalingMode="Fant", RenderOptions.EdgeMode="Aliased". None of this helped me and doesn't make the line look normal. Previously, one of the above or a combination of them always helped.

I tried to determine the system DPI value for the window and the value that WPF knows:

PresentationSource presentationSource = PresentationSource.FromVisual(window);                 
double wpfDpi = 96.0 * presentationSource.CompositionTarget.TransformToDevice.M11;                 
double currentDpi = GetDpiForWindow(hWnd);

Both values are the same (120) - the application knows about the scale.

Taget platform: NET Framework 4.5

OS: Windows 10 21H2


Solution

  • Add RenderOptions.EdgeMode="Aliased" to your Path object.

    This will force a 1 pixel wide line onto exact pixel boundaries, giving you a crisp graphic.

    You don't need UseLayoutRounding or SnapsToDevicePixels.

    <Path Stroke="Black" 
          StrokeThickness="1" 
          Data="M0,0 L10,0" 
          VerticalAlignment="Center" 
          HorizontalAlignment="Center"                                      
          RenderOptions.EdgeMode="Aliased" />