【问题标题】:.Net drawing clipping bug.Net 绘图剪切错误
【发布时间】:2010-09-06 03:22:26
【问题描述】:

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

有人知道解决方法吗?

【问题讨论】:

    标签: winforms graphics gdi+ system.drawing


    【解决方案1】:

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

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

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

    注意:我已经对线条进行了抗锯齿处理,并将您的剪切区域扩展了 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

    或者...

    以下也是可能的:

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

    这有效地使用区域组合/联合(我认为)与画布/控件的 ClientRectangle 进行剪辑。由于该区域与矩形不同,因此结果应该是预期的。可以通过添加来证明此代码可以工作

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

    在 setClip() 调用之后。这清楚地显示了仅出现在剪切区域中的黑色矩形。

    如果抗锯齿线不是一个选项,这可能是一个有效的解决方法。

    希望对你有帮助

    【讨论】:

      【解决方案2】:

      代码似乎有什么问题?

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

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

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

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-08
          相关资源
          最近更新 更多