winforms .Net绘图剪贴错误

j7dteeu8  于 2023-03-09  发布在  .NET
关注(0)|答案(3)|浏览(108)

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

在图形对象上设置反模式解决了这个问题。但这不是一个真实的的解决方案。
有人知道变通办法吗?

avkwfej4

avkwfej41#

这似乎是一个已知的错误...
下面的代码看起来可以按您的要求运行:

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.pdfhttp://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 );

这清楚地显示了黑色矩形只出现在剪切区域。
如果没有"消除线条锯齿"选项,则这可能是一个有效的解决方法。
希望这能帮上忙

eufgjt7s

eufgjt7s2#

缺陷是两条线段应该画得一样,但它们不是,因为在剪切区域内绘制的尖峰完全在剪切区域内,不应该以任何方式剪切,但它是。这是一个非常烦人的,但这会导致任何使用大量绘制线+剪切的软件看起来不专业,因为间隙可以出现在多边形中。

to94eoyn

to94eoyn3#

密码有什么问题吗?
好的,问题应该是......代码应该做什么,而它还没有做。
当我运行代码时,我看到2个红色的“尖峰”,我不是故意的吗?
通过在Rectangle声明后添加以下内容,您似乎在剪切的矩形区域内绘制了第一个棘波:
e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );
然后你执行一个转换,重置剪辑,所以在这一点上,我假设clientRectangle被用作适当的剪辑区域,然后试图重绘转换后的尖峰。

相关问题