2008-08-19 9 views
2

GDI + DrawLines Funktion hat einen Clipping-Fehler, der durch Ausführen der folgenden C# -Code reproduziert werden kann. Beim Ausführen des Codes erscheinen zwei Linienpfade, die identisch sein sollten, da beide innerhalb des Clipping-Bereichs liegen. Wenn jedoch der Ausschneidebereich festgelegt ist, wird eines der Liniensegmente nicht gezeichnet.. Net Zeichnung Clipping Bug

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

Das Einstellen des Anti-Modus auf dem Grafikobjekt löst dies. Aber das ist keine echte Lösung.

Kennt jemand eine Problemumgehung?

Antwort

0

Was scheint mit dem Code los zu sein?

OK, die Frage sollte sein ... was sollte der Code tun, dass es nicht schon tut.

Wenn ich den Code ausführen, sehe ich 2 rote "Spikes" bin ich nicht zu?

Sie erscheinen die erste Spitze in der gekappten Rechteck Region, indem es der folgenden nach der Erklärung des teh Rechtecks ​​verifiziert zu ziehen:

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

Dann führen Sie eine Übersetzung, setzen Sie den Clip so auf diesem Ich gehe davon aus, dass der ClientRectangle als die geeignete Clip-Region verwendet wird, und versuche dann, den übersetzten Spike neu zu schreiben. Wo ist der Käfer?!?

0

Der Fehler besteht darin, dass beide Liniensegmente identisch gezeichnet werden sollten, aber nicht, weil die innerhalb der Clipping-Region gezeichnete Spitze vollständig innerhalb der Clipping-Region liegt und nicht abgeschnitten werden sollte. Das ist sehr ärgerlich, aber das führt dazu, dass jede Software, die stark ziehende Linien verwendet, aufgrund von Lücken, die in den Polygonen auftreten können, unprofessionell aussieht.

3

Es scheint, dass dies ein bekannter Fehler ist ...

Der folgende Code erscheint zu funktionieren wie gewünscht:

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

Anmerkung: Ich habe die Linie AntiAlias'ed und erweitert Ihre Clipping-Bereich von 1

scheint es, dass die folgenden Arbeitsarounds helfen könnten (wenn auch nicht getestet):

  • Der Stift ist mehr als ein Pixel dick
  • Die Linie perfekt horizontal oder vertikal
  • Der Ausschnitt ist gegen die Fenstergrenzen statt einer Klammer Rechteck

Das Folgende ist eine Liste von Artikeln ist, das könnte/oder dann vielleicht wieder nicht helfen:

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

folgende ist auch möglich:

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

Diese effecivly Clips eine Region kombiniert/unioned mit (glaube ich) mit dem ClientRectangle der Leinwand/Kontrolle. Da die Region vom Rechteck abweicht, sollten die Ergebnisse den Erwartungen entsprechen. Dieser Code funktioniert nachweislich, indem er nach dem setClip() - Aufruf

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

hinzufügt. Dies zeigt deutlich das schwarze Rechteck, das nur in der ausgeschnittenen Region erscheint.

Dies könnte eine gültige Problemumgehung sein, wenn Anti-Aliasing der Linie keine Option ist.

Hoffe, das hilft