Lohit
Lohit

Reputation: 137

SnapsToDevicePixels issue

In my WPF app, I have created few Line elements and added inside a StackPanel. The thickness for all lines is set to 0.5. But when I render it, sometimes few lines are appearing blur. I tried setting SnapsToDevicePixels in the StackPanel but this makes the lines completely invisible. Now if I increase the line thickness to 1 or greater than 1 then SnapsToDevicePixels is working properly.

I am creating Line as shown below:

private void CreateLine(Double y1, Double y2, Double x1, Double x2, Double width, Double height)
{
    Line line = new Line() { Y1 = y1, Y2 = y2, X1 = x1, X2 = x2, Width = width, Height = height };
}

Here, if LineThickness is set to 0.5, x1 and x2 values will be 0.25 (LineThickenss / 2) and width is 0.5 (LineThickness).

Is there any minimum pixel value required to be set in order to make the SnapsToDevicePixels work in WPF?

Upvotes: 3

Views: 2634

Answers (3)

Artur A
Artur A

Reputation: 9119

It is not recommended to set fractional positions.

What means the half of WPF point? WPF will interpret 1 point as 1/96 inch. It differs in pixels for distinct monitors (96 DPI, 300 DPI).

WPF considers 1 point as 1 pixel in the usual monitors with 96 DPI. And UIElement.SnapsToDevicePixels works great. It tries to snap 0.5 pixel to the monitor grid. There are two results: enlarged version two one pixel or shortened version to 0 pixel (disappears).

If for some reason there is a need for exact 1 pixel (not 1 point) positioning then use GuidelineSet.

With .NET 4 or higher it is better to use Layout Rounding. It calculates pixel offsets at the UI position measuring level. While SnapsToDevicePixels works at the render level. The minus for Layout Rounding is that it is bad for dynamic moving.

Upvotes: 1

A.R.
A.R.

Reputation: 15685

No, there isn't a minimum per se. The blurriness you are experiencing is due to how WPf handles drawing in general. According to my experience you can't really do anything about it. Snapping to device pixels may give some reprieve, but can still be unpredictable.

Also there is a difference between a pixel and a WPF unit that makes things more complicated, though many techniques exist to translate between them.

A common approach to translating the pixel to WPF unit is:

Matrix m = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice;
double dpiFactor = 1/m.M11;
double lineThickness = dpiFactor * 1;   // Repace '1' with desired pixel size.

Here is a useful article on the topic: http://www.wpftutorial.net/DrawOnPhysicalDevicePixels.html

Upvotes: 1

Ross
Ross

Reputation: 4568

I solved many of my SnapToDevicePixels issues by using UseLayoutRounding instead:

In your case:

<StackPanel UseLayoutRounding="True">
    ...
</StackPanel>

I don't know if this will solve your issue, but from my experience, it's worth a try!

Upvotes: 4

Related Questions