Search code examples
c#.netwinformsgdi+gdi

What is, and how do I determine the cause of this strange exception with drawing a Rectangle?


I'm trying to draw a Rectangle in the OnPaint method of a custom control. It's not that I don't know how, it's just that I'm trying to do it properly this time (as opposed to creating a new Pen everytime OnPaint is called).

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SomeNamespace
{
    public partial class Window : Form
    {
        #region Designer Properties
        [Browsable(true), DisplayName("FormBorderColor"), Category("Appearance")]
        public Color FormBorderColor { get; set; }

        [Browsable(true), DisplayName("FormBorderThickness"), Category("Appearance")]
        public float FormBorderThickness { get; set; }

        #endregion

        private Pen formBorderPen;
        private Brush formBorderBrush;
        private Rectangle formBorderRectangle;

        public Window()
        {
            InitializeComponent();

            this.DoubleBuffered = true;

            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);

            this.SetStyle(ControlStyles.ContainerControl, true);
            this.SetStyle(ControlStyles.Selectable, true);

            // Initialize Border properties
            formBorderBrush = new SolidBrush(FormBorderColor);
            formBorderPen = new Pen(formBorderBrush, FormBorderThickness);
            formBorderRectangle = new Rectangle(0, 0, this.Width - (int)FormBorderThickness, this.Height - (int)FormBorderThickness);
        }

        protected override void OnPaint(PaintEventArgs paint)
        {
            switch(this.FormBorderStyle)
            {
                // If this FormBorderStyle is set to None, we can either
                // draw our own custom border, or no border at all.
                case FormBorderStyle.None:
                    // Draw Form Border if necessary.
                    Console.WriteLine(FormBorderColor);
                    Console.WriteLine(FormBorderThickness);

                    Console.WriteLine(formBorderBrush);
                    Console.WriteLine(formBorderPen);
                    Console.WriteLine(formBorderRectangle);

                    if(FormBorderThickness >= 1)
                    {
                        Console.WriteLine("Hooray?");
                        paint.Graphics.DrawRectangle(formBorderPen, formBorderRectangle);
                    }
                    else
                    {
                        Console.WriteLine("Can't draw border.");
                    }
                    break;
                default:
                    break;
            }

            base.OnPaint(paint);
        }
    }
}

... but, I've getting a bunch of exceptions and I believe it's because certain values are not being set when I'm expecting them to be set. But I don't know where else to set the values.

Details exceptions thrown

I'm going to take a wild stab in the dark here, and assume that these exceptions are being thrown because the values for these objects are being set in the constructor, however, I don't know where else to set these values. And from what I've seen all over MSDN, I thought I was setting the values in the right place.


CustomEndCap Exception:

'formBorderPen.CustomEndCap' threw an exception of type 'System.ArgumentException'

CustomStartCap Exception:

'formBorderPen.CustomStartCap' threw an exception of type 'System.ArgumentException'

DashPattern Exception:

'formBorderPen.DashPattern' threw an exception of type 'System.OutOfMemoryException'

What I don't understand is, why am I getting these exceptions? I'm not even playing around with Caps or DashPatterns. And why are the Pen and Brushes empty when I am manually setting them?



Solution

  • Your pen size could be zero for FormBorderThickness, which will cause some of those problems you are seeing.

    Also, you shouldn't use the form's constructor if you reference properties like Width or Height since those dimensions haven't been completely determined yet. You should use the OnLoad override for that.

    I would personally just create those pens and dispose of them in the Paint event, keep them local in scope. Same thing with that rectangle.