2010-11-30 39 views
2

J'ai créé un contrôle personnalisé, substitué son événement paint. Lorsque j'essaie de disposer des graphiques que je crée, ils disparaissent de l'écran. N'ai-je pas besoin d'utiliser disposer dans les contrôles personnalisés?C#: Est-il nécessaire de disposer d'un élément graphique dans un contrôle personnalisé?

EDIT: J'ai inclus un extrait de code. Pourquoi ne puis-je pas disposer l'objet graphique dc, créé à partir de PaintEventArgs? Ai-je besoin de le jeter?

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

Pourriez-vous poster un extrait de code? Dans un événement Paint, vous n'avez pas besoin de créer votre propre instance Graphics, mais de l'obtenir à partir de l'événement. –

+0

Cela devrait être winforms, non? – Vlad

+0

J'ai modifié la question et inclus un extrait de code. – Bildsoe

Répondre

7

Si vous n'avez pas créé l'objet graphique, vous ne devez pas le jeter, donc si votre fonction est protected override void OnPaint(PaintEventArgs e), vous ne disposerez pas de e.Graphics. Toutefois, si vous créez un objet graphique dans le gestionnaire OnPaint, vous devrez le mettre au rebut.

Règle générale (et c'est une règle de base et non une loi) si vous n'avez pas reçu votre objet d'un Graphics.FromXxxxx(), vous n'avez pas besoin d'appeler Dispose.

EDIT pour refléter le code que vous avez posté

Vous n'avez pas besoin de disposer de l'objet grapics parce qu'il a été transmis à vous un argument, mais vous ne surchargez pas fait l'événement de peinture pour votre controll. C'est la bonne façon de le faire.

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

     } 
} 

J'ai aussi retiré _dc que vous ne devriez pas être en train de modifier l'objet graphique lorsque vous n'êtes pas dans la fonction OnPaint.

0

Vous devriez être mise au rebut des contrôles au sein de votre contrôle personnalisé qui implémentent l'interface IDisposable. Assurez-vous que votre contrôle personnalisé implémente également cette interface (ajoutez une implémentation de la méthode Dispose()) afin de disposer correctement des contrôles (en appelant leurs méthodes Dispose()).

+0

Vous ne devez PAS mettre au rebut des objets dont vous n'êtes pas responsable. En écrasant 'OnPaint (e)' vous ne disposeriez pas '' dc' si vous avez 'var dc = e.Graphics' (ce qui est exactement ce que l'OP a fait). –

+0

J'ai spécifiquement déclaré que les contrôles doivent être éliminés, pas tous les objets. Le contrôle de l'OP devrait implémenter 'IDisposable' de sorte que tous les membres du contrôle soient éliminés correctement. Il n'y a aucun besoin de disposer de quoi que ce soit dans la méthode 'OnPaint()'. – Bernard

0

Sans un exemple, il est difficile de dire exactement où l'phoblem est, mais je peux deviner:

Dans votre événement OnPaint surchargée, il y a un paramètre PaintEventArgs. Vous devez effectuer tous les dessins sur l'objet Graphics de ce paramètre, et vous êtes prêt à partir. Cela devrait rendre vos graphiques.

+0

J'ai inclus un exemple de code dans la question. Je peins sur l'objet Graphics du paramètre. Mais plus tôt, lorsque j'ai utilisé un panneau par exemple, j'ai dû disposer les graphiques afin d'éviter les fuites de mémoire. Ma question est la suivante: Est-ce nécessaire/possible lorsque vous utilisez un contrôle personnalisé comme celui que j'ai créé? – Bildsoe