3

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 を設定したりして、この問題が解決されることを期待してさまざまな手法を試しましたが (余分なかすんだ灰色のバンドを削除します)、何も役に立たないようです。

何か案は?

4

1 に答える 1

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内で画像の問題を抱えている人のために...同じ問題が発生している場合、画像が拡大縮小、回転などされていない限り、これも修正されるはずです.. .画像をピクセル境界に合わせようとしているだけであれば、これでうまくいくはずです。)

于 2009-01-26T19:32:33.110 に答える