开发者

C#: Is it necessary to dispose of a graphics element inside a custom control?

I've created a custom control, overridden it's paint event. When I try to dispose of the graphics I create they just disappear from the screen. Don't I need to use dispose in custom controls?

EDIT: I've included a code snippet. Why can't i dispose the dc graphics object, created from the PaintEventArgs? Do i need to dispose it?

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

        }
}


If you did not create the graphics object you should not dispose it, so if you function signature is protected override void OnPaint(PaintEventArgs e) you would NOT dispose e.Graphics.

However if you create a graphics object in the OnPaint handler you will need to dispose it.

General rule of thumb (and it is a rule of thumb not a law) if you did not get your object from a Graphics.FromXxxxx() you do not need to call Dispose.

EDIT to reflect code you have posted

You do not need to dispose of the Grapics object because it was passed to you as a argument, however you are not actually overriding the paint event for your controll. This is the correct way to do it.

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

        }
}

I also removed _dc as you should not be editing the Graphics object when you are not inside the OnPaint function.


Without an example it's hard to say exactly where the phoblem is, but I can guess:

In your overriden OnPaint event, there's a parameter PaintEventArgs. You should perform all drawing onto this parameter's Graphics object, and you're good to go. That should make your graphics stick.


You should be disposing any controls within your custom control that implement the IDisposable interface. Ensure that your custom control implements this interface as well (add an implementation of the Dispose() method) so that you dispose of the controls within it properly (calling their Dispose() methods).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜