在WPF抗混叠假象 [英] Anti-aliasing artifacts in WPF

查看:95
本文介绍了在WPF抗混叠假象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有,当我试图使用抗锯齿的图形WPF中一个奇怪的渲染问题。

I have a bizarre rendering issue when I'm trying to use anti-aliased graphics in WPF.

下面是一个简化版本。

如果我用下面的XAML

If I use the following 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);
        }
    }
}

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

I get a strange rendering issue with the anti-aliasing where the cropping rectangle edge is (running the program, it will be fairly obvious, but it's a hazy gray line where the cropping rectangle is truncating the paths.)

我已经试过各种技术,如对准控制特定的像素,并且在希望,这将解决这个问题(删除多余的朦胧灰带)上设置的各种控制SnapsToDevicePixels,但似乎没有任何帮助。

I've tried various techniques like aligning the controls to specific pixels, and setting SnapsToDevicePixels on the various controls in the hopes that this would solve this issue (remove the extra hazy gray band), but nothing seems to help.

任何想法?

推荐答案

原来,这是因为虽然窗口是,当然,在一个像素边界对齐时,窗口内的网格可能不大。修复这是不是太困难,但它可能需要一段时间才能弄清楚怎么做。

Turns out that this is because although the window is, of course, aligned on a pixel boundry, the grid within the window may not be. Fixing this isn't overly difficult, but it can take a while to figure out what to do.

有一个名为应该得到的一切正确对齐SnapsToDevicePixels不错的功能。而且,不幸的是,不管是什么原因,它似乎并没有在所有的工作(这似乎是一个理解错误)。那么怎么办?

There is a nice feature called SnapsToDevicePixels that should get everything aligned correctly. And, sadly, for whatever reason, it doesn't seem to work at all (this seems to be an understood bug). So what to do?

首先,网格必须在象素边界对准的(即不居中,或类似的东西,因为如果窗口具有奇数个在水平或垂直方向上的象素则网格,并且因此网格内容,将错位。)

First, the grid must be aligned at a pixel boundry (ie not centered, or something like that since if the window has an odd number of pixels in either the horizontal or vertical direction then the grid, and hence the grid contents, will be misaligned.)

不过,还有其他的问题需要处理......一旦你开始滚动滚动条,神器再次出现!这是因为滚动条不一定滚动内容像素的整数倍。为了解决这个问题,我捕捉到了ScrollViewer中的一些事件来设置滚动位置的整数值。

But then, there are other issues to deal with...as soon as you start to scroll the scroll bars, the artifact reappears! This is because the scrollbars do not necessarily scroll the content an integer number of pixels. To deal with that, I capture some events in the ScrollViewer to set the scrolling location to integer values.

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);
    }
}

这样做,一切似乎很好。

Do that, and all seems to be well.

(作为一个方面说明,对于那些有内部ScrollViews图像问题的人......如果你正在运行到同一个问题,这应该解决这个问题为好,只要图像不进行缩放,旋转,等等......只要你只是想将图像调整到一个像素的边界,这应该做的工作。)

(As a side note, for people that are having Image problems inside ScrollViews...if you're running into the same issue, this should fix that as well, so long as the Image isn't scaled, rotated, etc...so long as you're just trying to align the image to a pixel boundry, this should do the job.)

这篇关于在WPF抗混叠假象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆