How to throw an exception?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Tyler Wiebe
    New Member
    • Mar 2011
    • 66

    #1

    How to throw an exception?

    This is my first time using exceptions, and I can't seem to make the exception get thrown. This is meant for painting this shape on the form. If I have the curve height more then the height of the object, all my form does is creates red X's for all of the controls.

    So what am I doing wrong?

    P.S. It works fine if the curve height is less then the object height.

    Code:
        public class BottomCurve
        {
            public BottomCurve(int Width, int Height, int CurveHeight)
            {
                if (CurveHeight >= Height) throw new System.Exception("The curve height cannot be greater then or equal to the height of this object");
    
                this.ISize = new System.Drawing.Size(Width, Height);
    
                this.ICurve = new System.Drawing.Point[]
                {
                    new System.Drawing.Point(0, this.Height),
                    new System.Drawing.Point(this.Width / 2, this.Height - CurveHeight),
                    new System.Drawing.Point(this.Width, this.Height)
                };
    
                this.IGraphicsPath = new System.Drawing.Drawing2D.GraphicsPath();
                this.IGraphicsPath.StartFigure();
    
                this.IGraphicsPath.AddLine(0, 0, 0, this.Height);
                this.IGraphicsPath.AddCurve(ICurve);
                this.IGraphicsPath.AddLine(this.Width, this.Height, this.Width, 0);
                this.IGraphicsPath.AddLine(this.Width, 0, 0, 0);
    
                this.IGraphicsPath.CloseFigure();
            }
    
            internal System.Drawing.Point[] ICurve;
            internal System.Drawing.Drawing2D.GraphicsPath IGraphicsPath;
            public System.Drawing.Drawing2D.GraphicsPath GraphicsPath { get { return this.IGraphicsPath; } }
            
            internal System.Drawing.Size ISize;
            public System.Drawing.Size Size { get { return this.ISize; } }
            public int Width { get { return this.Size.Width; } }
            public int Height { get { return this.Size.Height; } }
        }

    HOW TO USE:

    Code:
            public void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
            {
                BottomCurve BC = new BottomCurve(this.Width, 100, 40);
                e.Graphics.FillPath(new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(255, 255, 0, 0)), BC.GraphicsPath);
            }
  • GaryTexmo
    Recognized Expert Top Contributor
    • Jul 2009
    • 1501

    #2
    You get that red X when an unhandled exception occurs in a paint. It appears to be how the .NET framework handles it. It also looks like when an unhandled exception occurs, you can't really recover from it. I took your code and had the curve height set by a variable that I incremented to / decremented from with buttons and once it went into an unhandled exception it didn't come back, even if I reduced the curve height.

    Anyway, this unhandled exception is entirely your doing :D On line 5 of your code above, you're throwing an exception when the curve height is greater than the height... which you intend, but what you're not doing is catching that exception anywhere. This is where the try/catch block comes in... you attempt something and if there's an exception, you handle it appropriately. I made the following changes to your paint method:

    Code:
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
    
        try
        {
            BottomCurve curve = new BottomCurve(this.Width, this.Height / 2, m_curveHeight);
            e.Graphics.FillPath(new SolidBrush(Color.Yellow), curve.GraphicsPath);
        }
        catch (Exception ex)
        {
            e.Graphics.DrawString(ex.Message, this.Font, Brushes.Red, new PointF(0f, (float)this.Font.Height));
        }
    
        e.Graphics.DrawString("Curve Height: " + m_curveHeight.ToString(), this.Font, Brushes.Black, new PointF(0f, 0f));
    }
    Here I'm putting the curve instantiation inside a try/catch block. If there's an exception, I output an error message. If there's no exception, the try block executes completely and will draw the curve.

    There is something you should be aware of though. There is an overhead associated with exception handling and while today's processors handle it fairly well, you may want to consider a more efficient approach. There are two places I can see where you can immediately increase your efficiency.

    1) Instead of having a curve generated in the constructor so that you need to make a new curve every cycle, consider instantiating a single curve object and then updating it. There's overhead associated with creating, and subsequently destroying, an object. When you do this in a draw loop (assuming you have a draw loop) you're causing needless object creations which will only get released for garbage collection immediately. So instead of doing that work in the constructor, maybe move it to a GenerateCurve method which takes the same parameters. When called, it will update the class members and regenerate the curve.

    2) Instead of an exception, consider a return value. If the curve generation sees anything it doesn't like, it can just return false. On the drawing side, if a return value of false is seen the appropriate action can be taken. This does take away from the error messages that can be seen though, but you can do other things like return a string instead of a boolean. If the string is empty, curve generation was successful. This might not be preferable to you though.

    As I mentioned, today's processors can handle exception handling fairly well so the second one isn't that big a deal. Actually neither are, but they are something to consider if you're going to have a high drawing demand. If not, carry right on :)

    Comment

    Working...