2010-11-30 13 views
2

Ich habe ein benutzerdefiniertes Steuerelement erstellt und das Paint-Ereignis überschrieben. Wenn ich versuche, die von mir erstellten Grafiken zu entfernen, verschwinden sie einfach vom Bildschirm. Muss ich nicht in benutzerdefinierten Steuerelementen verwenden?C#: Ist es erforderlich, ein Grafikelement in einem benutzerdefinierten Steuerelement zu entfernen?

EDIT: Ich habe ein Code-Snippet enthalten. Warum kann ich das DC-Grafikobjekt, das aus den PaintEventArgs erstellt wurde, nicht entfernen? Muss ich es entsorgen?

class canvas : Control 
    { 

     PointF mouseDown; 

     float newX; 
     float newY; 
     float zoomFactor = 1F; 

     Graphics _dc; 

     public canvas() 
     { 
      this.DoubleBuffered = true; 
      mouseDown = new PointF(0F, 0F); 
      this.Paint += new PaintEventHandler(ctrl_Paint); 
     } 

     private void ctrl_Paint(object sender, PaintEventArgs e) 
     { 


      Graphics dc = e.Graphics; 
      _dc = dc; 

      dc.SmoothingMode = SmoothingMode.AntiAlias; 

      Color gridColor = Color.FromArgb(230, 230, 230); 
      Pen gridPen = new Pen(gridColor, 1); 

      float offX = (float)((Math.Sqrt(Math.Pow(newX, 2)) % (30 * zoomFactor))); 
      float offY = (float)((Math.Sqrt(Math.Pow(newY, 2)) % (30 * zoomFactor))); 

      for (float y = offY; y < this.Height; y = y + 30 * zoomFactor) 
      { 
       dc.DrawLine(gridPen, 0, y, this.Width, y); 
      } 
      for (float x = offX; x < this.Width; x = x + 30 * zoomFactor) 
      { 
       dc.DrawLine(gridPen, x, 0, x, this.Height); 
      } 

      dc.TranslateTransform(newX, newY); 
      dc.ScaleTransform(zoomFactor, zoomFactor, MatrixOrder.Prepend); 

      float XPosition = 10; 
      float YPosition = 10; 
      float CornerRadius = 5; 
      float Width = 50; 
      float Height = 50; 

      Color BoxColor = Color.FromArgb(0, 0, 0); 
      Pen BoxPen = new Pen(BoxColor, 2); 

      GraphicsPath Path = new GraphicsPath(); 

      Path.AddLine(XPosition + CornerRadius, YPosition, XPosition + Width - (CornerRadius * 2), YPosition); 
      Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition, CornerRadius * 2, CornerRadius * 2, 270, 90); 
      Path.AddLine(XPosition + Width, YPosition + CornerRadius, XPosition + Width, YPosition + Height - (CornerRadius * 2)); 
      Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 0, 90); 
      Path.AddLine(XPosition + Width - (CornerRadius * 2), YPosition + Height, XPosition + CornerRadius, YPosition + Height); 
      Path.AddArc(XPosition, YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 90, 90); 
      Path.AddLine(XPosition, YPosition + Height - (CornerRadius * 2), XPosition, YPosition + CornerRadius); 
      Path.AddArc(XPosition, YPosition, CornerRadius * 2, CornerRadius * 2, 180, 90); 

      Path.CloseFigure(); 

      dc.DrawPath(BoxPen, Path); 

      LinearGradientBrush lgb = new LinearGradientBrush(new PointF(XPosition + (Width/2), YPosition), new PointF(XPosition + (Width/2), YPosition + Height), Color.RosyBrown, Color.Red); 

      dc.FillPath(lgb, Path); 

     } 
} 
+0

Können Sie ein Code-Snippet posten? In einem Paint-Ereignis müssen Sie keine eigene Graphics-Instanz erstellen, sondern sie aus dem Ereignis abrufen. –

+0

Das sollte winforms sein, oder? – Vlad

+0

Ich habe die Frage bearbeitet und ein Code-Snippet eingefügt. – Bildsoe

Antwort

7

Wenn Sie das Grafikobjekt nicht erstellt haben, sollten Sie es nicht entsorgen, wenn Sie also die Signatur protected override void OnPaint(PaintEventArgs e) haben, würden Sie e.Graphics NICHT entsorgen.

Wenn Sie jedoch ein Grafikobjekt im OnPaint-Handler erstellen, müssen Sie es entfernen.

Allgemeine Faustregel (und es ist eine Faustregel, kein Gesetz) Wenn Sie Ihr Objekt nicht von einem Graphics.FromXxxxx() erhalten haben, müssen Sie Dispose nicht aufrufen.

EDIT Code zu reflektieren Sie haben geschrieben

Sie brauchen nicht von der Grapics Objekt zu entsorgen, weil es Ihnen als Argument übergeben wurde, aber Sie sind nicht wirklich für Ihre controll das Paint-Ereignis überschreiben. Dies ist der richtige Weg, es zu tun.

class canvas : Control 
    { 

     PointF mouseDown; 

     float newX; 
     float newY; 
     float zoomFactor = 1F; 


     public canvas() 
     { 
      this.DoubleBuffered = true; 
      mouseDown = new PointF(0F, 0F); 
     } 

     protected override void OnPaint(PaintEventArgs e) 
     { 
      base.OnPaint(e); 
      Graphics dc = e.Graphics; 

      dc.SmoothingMode = SmoothingMode.AntiAlias; 

      Color gridColor = Color.FromArgb(230, 230, 230); 
      Pen gridPen = new Pen(gridColor, 1); 

      float offX = (float)((Math.Sqrt(Math.Pow(newX, 2)) % (30 * zoomFactor))); 
      float offY = (float)((Math.Sqrt(Math.Pow(newY, 2)) % (30 * zoomFactor))); 

      for (float y = offY; y < this.Height; y = y + 30 * zoomFactor) 
      { 
       dc.DrawLine(gridPen, 0, y, this.Width, y); 
      } 
      for (float x = offX; x < this.Width; x = x + 30 * zoomFactor) 
      { 
       dc.DrawLine(gridPen, x, 0, x, this.Height); 
      } 

      dc.TranslateTransform(newX, newY); 
      dc.ScaleTransform(zoomFactor, zoomFactor, MatrixOrder.Prepend); 

      float XPosition = 10; 
      float YPosition = 10; 
      float CornerRadius = 5; 
      float Width = 50; 
      float Height = 50; 

      Color BoxColor = Color.FromArgb(0, 0, 0); 
      Pen BoxPen = new Pen(BoxColor, 2); 

      GraphicsPath Path = new GraphicsPath(); 

      Path.AddLine(XPosition + CornerRadius, YPosition, XPosition + Width - (CornerRadius * 2), YPosition); 
      Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition, CornerRadius * 2, CornerRadius * 2, 270, 90); 
      Path.AddLine(XPosition + Width, YPosition + CornerRadius, XPosition + Width, YPosition + Height - (CornerRadius * 2)); 
      Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 0, 90); 
      Path.AddLine(XPosition + Width - (CornerRadius * 2), YPosition + Height, XPosition + CornerRadius, YPosition + Height); 
      Path.AddArc(XPosition, YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 90, 90); 
      Path.AddLine(XPosition, YPosition + Height - (CornerRadius * 2), XPosition, YPosition + CornerRadius); 
      Path.AddArc(XPosition, YPosition, CornerRadius * 2, CornerRadius * 2, 180, 90); 

      Path.CloseFigure(); 

      dc.DrawPath(BoxPen, Path); 

      LinearGradientBrush lgb = new LinearGradientBrush(new PointF(XPosition + (Width/2), YPosition), new PointF(XPosition + (Width/2), YPosition + Height), Color.RosyBrown, Color.Red); 

      dc.FillPath(lgb, Path); 

     } 
} 

Ich entfernte auch _dc wie Sie nicht das Graphics-Objekt Bearbeitung werden sollten, wenn Sie nicht innerhalb der Funktion OnPaint sind.

0

Sie sollten alle Kontrollen innerhalb Ihrer benutzerdefinierten Kontrolle werden Entsorgung, die die IDisposable-Schnittstelle implementieren. Stellen Sie sicher, dass Ihr benutzerdefiniertes Steuerelement auch diese Schnittstelle implementiert (Fügen Sie eine Implementierung der Dispose()-Methode hinzu), damit Sie die darin enthaltenen Steuerelemente ordnungsgemäß entsorgen (indem Sie ihre Dispose() Methoden aufrufen).

+0

Sie sollten keine Gegenstände entsorgen, die Sie nicht zu entsorgen haben. Wenn Sie 'OnPaint (e)' überschreiben, würden Sie 'dc' nicht ** entledigen, wenn Sie' var dc = e.Graphics' hätten (was genau das ist, was das OP getan hat). –

+0

Ich sagte ausdrücklich, dass Kontrollen sollten nicht alle Objekte angeordnet werden. Die Kontrolle des OP sollte "IDisposable" einführen, damit alle Mitglieder der Kontrolle ordnungsgemäß entsorgt werden können. Es besteht keine Notwendigkeit, etwas in der OnPaint() 'Methode zu beseitigen. – Bernard

0

Ohne ein Beispiel genau, es ist schwer zu sagen, wo die phoblem ist, aber ich denke, kann:

In Ihrem überschriebenen OnPaint Ereignis, es ist ein Parameter PaintEventArgs. Sie sollten alle Zeichen auf dem Graphics-Objekt dieses Parameters ausführen, und Sie können loslegen. Das sollte deine Grafik haften lassen.

+0

Ich habe Beispielcode in die Frage eingefügt. Ich male auf das Graphics-Objekt des Parameters. Aber früher, als ich zum Beispiel auf ein Panel zurückgegriffen habe, musste ich die Grafiken entsorgen, um Speicherlecks zu vermeiden. Meine Frage ist: Ist dies notwendig, wenn ich ein benutzerdefiniertes Steuerelement verwende, das ich erstellt habe? – Bildsoe