2

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 模式可以解决此问题。但这不是一个真正的解决方案。

有人知道解决方法吗?

4

3 回答 3

3

It appears that this is a known bug...

The following code appears to function as you requested:

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

Note: I have AntiAlias'ed the line and extended your clipping region by 1

it appears that the following work arounds might help (although not tested):

  • The pen is more than one pixel thick
  • The line is perfectly horizontal or vertical
  • The clipping is against the window boundaries rather than a clip rectangle

The following is a list of articles that might / or then again might not help:

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...

the following is also possible:

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

This effecivly clips using a region combined/unioned (I think) with the ClientRectangle of the canvas/Control. As the region is difned from the rectangle, the results should be what is expected. This code can be proven to work by adding

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

after the setClip() call. This clearly shows the black rectangle only appearing in the clipped region.

This could be a valid workaround if Anti-Aliasing the line is not an option.

Hope this helps

于 2008-08-19T20:43:20.257 回答
0

代码似乎有什么问题?

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

当我运行代码时,我看到了 2 个红色的“尖峰”,我不介意吗?

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

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

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

于 2008-08-19T06:52:57.297 回答
0

错误是两条线段应该绘制相同,但它们不是因为在剪切区域内绘制的尖峰完全在剪切区域内,不应以任何方式剪切,但它确实如此。这是一个非常烦人的问题,但由于多边形中可能出现间隙,这会导致任何大量使用绘图线 + 剪裁的软件看起来不专业。

于 2008-08-19T09:17:37.113 回答