2010-11-30 17 views
2

私はカスタムコントロールを作成しました、それはpaintイベントをオーバーライドしました。作成したグラフィックを破棄しようとすると、スクリーンから消えるだけです。カスタムコントロールでdisposeを使用する必要はありませんか?C#:グラフィックス要素をカスタムコントロール内に配置する必要はありますか?

編集:コードスニペットを追加しました。なぜ、PaintEventArgsから作成されたDCグラフィックスオブジェクトを処分できないのですか?私はそれを処分する必要がありますか?

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

コードスニペットを投稿できますか?ペイントイベントでは、独自のGraphicsインスタンスを作成する必要はなく、イベントから取得する必要があります。 –

+0

これはwinformsでなければなりません。 – Vlad

+0

質問を編集してコードスニペットが含まれています。 – Bildsoe

答えて

7

グラフィックスオブジェクトを作成していない場合は、それを破棄しないでください。関数シグネチャがprotected override void OnPaint(PaintEventArgs e)の場合、e.Graphicsは処分しません。

ただし、OnPaintハンドラでグラフィックスオブジェクトを作成する場合は、そのオブジェクトを破棄する必要があります。

Graphics.FromXxxxx()からオブジェクトを取得しなかった場合は、Disposeを呼び出す必要はありません(これは大雑把な法則です)。あなたはそれはしかし、あなたが実際にあなたのcontrollペイントイベントをオーバーライドしていない、引数としてあなたに渡されたので、あなたがGrapicsオブジェクトを処分する必要はありません

を掲載しているコードを反映する

EDIT。これは正しい方法です。

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

     } 
} 

あなたがのOnPaint関数内でないときは、Graphicsオブジェクトを編集すべきではないと私はまた、_dcを削除しました。

0

あなたはIDisposableインターフェイスを実装するカスタムコントロール内の任意のコントロールを配置する必要があります。カスタムコントロールがこのインターフェイスを実装していることを確認してください(Dispose()メソッドの実装を追加してください)。コントロールを適切に処分するようにしてください(Dispose()メソッドを呼び出す)。

+0

処分する責任を負わないオブジェクトは廃棄しないでください。 'OnPaint(e)'をオーバーライドすると、 'var dc = e.Graphics'(これはOPとまったく同じです)を行った場合、' dc'を処理しません**。 –

+0

私はコントロールがすべてのオブジェクトではなく、処分されるべきであると具体的に述べました。 OPのコントロールは、コントロールのメンバーのいずれかが適切に配置されるように、「IDisposable」を実装する必要があります。 'OnPaint()'メソッドには何も処理する必要はありません。 – Bernard

0

例がなければ、それはphoblemがある場所を正確に言うのは難しいのですが、私は推測することができます:あなたのオーバーライドOnPaintイベントで

は、パラメータPaintEventArgsのがあります。すべての描画をこのパラメータのGraphicsオブジェクトに実行する必要があります。それはあなたのグラフィックを固執させるはずです。

+0

質問にexample-codeを含めました。私はパラメータのGraphicsオブジェクトにペイントします。しかし、以前は例えばパネルを描いたときに、メモリリークを防ぐためにグラフィックスを処分しなければなりませんでした。私の質問は:これは、必要な/私は作成したようなカスタムコントロールを使用して可能ですか? – Bildsoe

関連する問題