当我尝试在WPF中使用抗锯齿图形时,我有一个奇怪的渲染问题。
这是一个简化版本。
如果我使用以下XAML
<Window x:Class="RenderingBug.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Width="300" Height="300">
<Grid Name="myGrid" Background="AntiqueWhite" Width="250" Height="250">
<ScrollViewer Name="myScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas Height="500" Width="500" Name="myCanvas" />
</ScrollViewer>
</Grid>
</Window>
以下cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace RenderingBug
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
PathFigureCollection pfc = new PathFigureCollection();
PathFigure pf = new PathFigure();
pf.StartPoint = new Point(100, 20);
LineSegment ls = new LineSegment();
ls.Point = new Point(20, 100);
PathSegmentCollection psc = new PathSegmentCollection();
psc.Add(ls);
pf.Segments = psc;
pfc.Add(pf);
PathGeometry pg = new PathGeometry(pfc);
RectangleGeometry clippingRectangle = new RectangleGeometry(new Rect(0, 0, 80, 80));
Path p1 = new Path();
p1.ClipToBounds = true;
p1.Clip = clippingRectangle;
p1.StrokeDashCap = PenLineCap.Square;
p1.Stroke = Brushes.Black;
p1.StrokeThickness = 30;
p1.Data = pg;
myCanvas.Children.Add(p1);
Path p2 = new Path();
p2.ClipToBounds = true;
p2.Clip = clippingRectangle;
p2.StrokeDashCap = PenLineCap.Square;
p2.Stroke = Brushes.White;
p2.StrokeThickness = 10;
p2.Data = pg;
myCanvas.Children.Add(p2);
}
}
}
我得到了一个奇怪的渲染问题,即使用裁剪矩形边缘的抗锯齿(运行程序,这将是相当明显的,但它是一条模糊矩形截断路径的朦胧灰线。)
我尝试了各种技术,比如将控件与特定像素对齐,并在各种控件上设置SnapsToDevicePixels,希望这可以解决这个问题(删除额外的模糊灰色条带),但似乎没有任何帮助。
有什么想法吗?
答案 0 :(得分:3)
事实证明,这是因为虽然窗口当然是在像素边界上对齐,但窗口内的网格可能不是。解决这个问题并不困难,但要弄清楚要做什么可能需要一段时间。
有一个很好的功能叫做SnapsToDevicePixels,可以正确对齐所有内容。而且,遗憾的是,无论出于何种原因,它似乎根本不起作用(这似乎是一个被理解的错误)。那该怎么办?
首先,网格必须在像素边界处对齐(即不居中,或类似的东西,因为如果窗口在水平或垂直方向上具有奇数个像素,那么网格,因此网格内容,将会错位。)
但是,还有其他问题要处理......一旦你开始滚动滚动条,工件就会重新出现!这是因为滚动条不一定将内容滚动整数个像素。为了解决这个问题,我在ScrollViewer中捕获了一些事件,将滚动位置设置为整数值。
private void workingAreaScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
{
double w = e.NewSize.Width;
double h = e.NewSize.Height;
workingAreaScrollViewer.Width = Math.Round(w);
workingAreaScrollViewer.Height = Math.Round(h);
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.A)
{
workingAreaCanvas.Children.Remove(p2);
}
if (e.Key == Key.Z && p2.Parent != workingAreaCanvas)
{
workingAreaCanvas.Children.Add(p2);
}
}
这样做,一切似乎都很好。
(作为旁注,对于在ScrollViews中遇到图像问题的人来说......如果你遇到同样的问题,这也应该解决这个问题,只要图像没有缩放,旋转,等等......只要您尝试将图像与像素边界对齐,就可以完成这项任务。)