2009-01-21 95 views
3

当我尝试在WPF中使用抗锯齿图形时,出现奇怪的渲染问题。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); 
     } 
    } 
} 

我得到一个奇怪的渲染问题,与在裁剪矩形边缘(运行程序抗锯齿,这将是相当明显的,但它是一个朦胧的灰色线,其中裁剪矩形截断路径)。

我已经尝试了各种技术,如调整控制ols到特定的像素,并在各种控制上设置SnapsToDevicePixels,希望这可以解决这个问题(去除额外的模糊灰色带),但似乎没有任何帮助。

任何想法?

回答

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中存在图像问题的人...如果您遇到同样的问题,这也应该解决这个问题,只要图像不缩放,旋转等等......只要你只是想把图像对准像素边界,这应该可以完成这项工作。)