C #: необходимо ли утилизировать графический элемент внутри пользовательского элемента управления? - PullRequest
3 голосов
/ 30 ноября 2010

Я создал пользовательский элемент управления, переопределив его событие рисования. Когда я пытаюсь избавиться от созданной графики, они просто исчезают с экрана. Разве мне не нужно использовать dispose в пользовательских элементах управления?

РЕДАКТИРОВАТЬ: Я включил фрагмент кода. Почему я не могу удалить графический объект DC, созданный из PaintEventArgs? Нужно ли мне его утилизировать?

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

        }
}

Ответы [ 3 ]

9 голосов
/ 30 ноября 2010

Если вы не создали графический объект, вам не следует его утилизировать, поэтому, если вы используете функцию сигнатуры protected override void OnPaint(PaintEventArgs e), вы НЕ будете утилизировать e.Graphics.

Однако, если вы создаете графический объект в обработчике OnPaint, вам нужно будет его утилизировать.

Общее эмпирическое правило (и это эмпирическое правило, а не закон), если вы не получили свой объект от Graphics.FromXxxxx(), вам не нужно вызывать Dispose.

РЕДАКТИРОВАТЬ, чтобы отразить код, который вы отправили

Вам не нужно избавляться от объекта Grapics, поскольку он был передан вам в качестве аргумента, однако вы фактически не переопределяете событие рисования для своего элемента управления. Это правильный способ сделать это.

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

        }
}

Я также удалил _dc, так как вам не следует редактировать графический объект, когда вы не находитесь внутри функции OnPaint.

0 голосов
/ 30 ноября 2010

Без примера трудно сказать, где именно находится проблема, но я могу догадаться:

В переопределенном событии OnPaint есть параметр PaintEventArgs.Вы должны выполнить все рисование на объекте Graphics этого параметра, и все готово.Это должно сделать вашу графику палкой.

0 голосов
/ 30 ноября 2010

Вы должны использовать любые элементы управления в вашем пользовательском элементе управления, которые реализуют интерфейс IDisposable.Убедитесь, что ваш пользовательский элемент управления также реализует этот интерфейс (добавьте реализацию метода Dispose()), чтобы вы правильно распоряжались элементами управления внутри него (вызывая их методы Dispose()).

...