Привязка к пикселям

90

Как известно, в WPF используется независимая от устройств система рисования. Размеры таких вещей, как шрифты и фигуры, указываются с применением "виртуальных" пикселей, которые совпадают с нормальными пикселями на обычных дисплеях с 96 dpi, но масштабируются для дисплеев с более высоким разрешением. Другими словами, если рисуется прямоугольник шириной в 50 пикселей, то в действительности он может отображаться большим или меньшим количеством пикселей — в зависимости от устройства. Такое преобразование между независимыми от устройства единицами и физическими пикселями происходит автоматически, и обычно думать о нем не приходится.

Отношение между пикселями систем с разными показателями dpi редко выражается целым числом. Например, 50 пикселей на мониторе с 96 dpi превращаются в 62,4996 пикселей на мониторе с 120 dpi. (В этом нет никакой ошибки — фактически, WPF всегда позволяет использовать дробные значения двойной точности при указании значений в независимых от устройства единицах.) Очевидно, что нет способа поместить границу фигуры или линии в точку, находящуюся между пикселями.

WPF компенсирует это посредством сглаживания. Например, при отображении красной линии длиной в 62,4992 пикселя WPF заполняет первые 62 пикселя нормально, а затем текстурирует 63-й пиксель цветом, значение которого находится между цветом линии (красным) и цветом фона. Однако здесь кроется ловушка. При рисовании прямых линий, прямоугольников или многоугольников с прямыми углами такое автоматическое сглаживание может привести к некоторой нечеткости границ фигуры.

Можно было бы предположить, что данная проблема появляется только при запуске приложения на дисплее, имеющем разрешение, не равное 96 dpi. Однако это не обязательно так, поскольку размеры и положение фигур могут задаваться дробными числами и дробными координатами, что даст тот же эффект. И хотя дробные длины и координаты редко используются при рисовании фигур, но фигуры с изменяемым размером — т.е. такие, которые растягиваются вместе с размерами контейнера или которые помещаются в Viewbox — почти всегда рано или поздно принимают дробные размеры. Аналогично, линии нечетной толщины имеют дробное число пикселей на каждой стороне.

Эффект размытой границы не всегда является проблемой. Фактически, если такое поведение не устраивает, можно заставить WPF не применять сглаживание для определенной фигуры. Вместо этого WPF будет округлять все измерения до ближайшего ряда пикселей устройства. Это средство, называемое привязкой к пикселям, задается установкой в true свойства SnapsToDevicePixels класса UIElement.

Чтобы увидеть разницу, взгляните на увеличенное окно на рисунке в котором сравниваются два прямоугольника. В нижнем прямоугольнике используется привязка к пикселям, а в верхнем — нет. Если внимательно присмотреться, то можно заметить тонкую линию более светлого цвета вдоль верхней и левой граней непривязанного прямоугольника:

Эффект привязки к пикселям
Пройди тесты
Лучший чат для C# программистов