.Net绘图剪辑bug

时间:2008-08-19 01:11:28

标签: winforms graphics gdi+ system.drawing

GDI + DrawLines函数有一个剪辑错误,可以通过运行以下c#代码重现。运行代码时,会出现两条相同的线路径,因为它们都在裁剪区域内。但是当设置剪切区域时,不绘制其中一个线段。

protected override void OnPaint(PaintEventArgs e)
{
   PointF[] points = new PointF[] { new PointF(73.36f, 196), 
             new PointF(75.44f, 32), 
             new PointF(77.52f, 32), 
             new PointF(79.6f, 196), 
             new PointF(85.84f, 196) };

   Rectangle b = new Rectangle(70, 32, 20, 164);         
   e.Graphics.SetClip(b);
   e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
   e.Graphics.TranslateTransform(80, 0);
   e.Graphics.ResetClip();
   e.Graphics.DrawLines(Pens.Red, points);
 }

在图形对象上设置antials模式可解决此问题。但这不是一个真正的解决方案。

有人知道解决方法吗?

3 个答案:

答案 0 :(得分:3)

看来这是一个已知的错误......

以下代码似乎按您的要求运行:

protected override void OnPaint(PaintEventArgs e)
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        e.Graphics.SmoothingMode =  System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        Rectangle b = new Rectangle(70, 32, 20, 165);
        e.Graphics.SetClip(b);
        e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
        e.Graphics.TranslateTransform(80, 0);
        e.Graphics.ResetClip();           
        e.Graphics.DrawLines(Pens.Red, points);
    }

注意:我有AntiAlias的线,并将剪裁区域扩展1

看来以下解决方法可能有所帮助(虽然没有经过测试):

  • 笔的厚度超过一个像素
  • 该线条完全水平或垂直
  • 裁剪是针对窗口边界而不是剪裁矩形

以下是可能/可能无效的文章列表:

http://www.tech-archive.net/pdf/Archive/Development/microsoft.public.win32.programmer.gdi/2004-08/0350.pdf http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.gdi/2004-08/0368.html

... OR

以下也是可能的:

protected override void OnPaint ( PaintEventArgs e )
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        Rectangle b = new Rectangle( 70, 32, 20, 164 );
        Region reg = new Region( b );
        e.Graphics.SetClip( reg, System.Drawing.Drawing2D.CombineMode.Union);
        e.Graphics.DrawLines( Pens.Red, points ); // clipped incorrectly
        e.Graphics.TranslateTransform( 80, 0 );
        e.Graphics.ResetClip();
        e.Graphics.DrawLines( Pens.Red, points );
    }

这有效地剪辑使用区域组合/联合(我认为)与canvas / Control的ClientRectangle。由于该区域与矩形不同,因此结果应该是预期的。通过添加

,可以证明此代码可以正常工作
e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );
在setClip()调用之后

。这清楚地表明黑色矩形仅出现在剪裁区域中。

如果无法选择抗锯齿线,这可能是一种有效的解决方法。

希望这有帮助

答案 1 :(得分:0)

错误是两个线段应该绘制相同,但它们不是因为在裁剪区域内绘制的尖峰完全在裁剪区域内,不应该以任何方式裁剪,但它是。这是非常令人讨厌的,但是由于多边形中可能出现的间隙,导致任何使用绘制线严重+剪裁的软件看起来不专业。

答案 2 :(得分:0)

代码似乎有什么问题?

好的,问题应该是......代码应该做什么,它还没有。

当我运行代码时,我看到2个红色'尖峰'我不知道吗?

您似乎在剪裁的矩形区域内绘制第一个尖峰,通过在声明矩形后添加以下内容来验证:

e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );

然后你执行翻译,重置剪辑,所以此时我假设clientRectangle被用作适当的剪辑区域,然后尝试重新转换已翻译的尖峰。错误在哪里?!?