Click here to Skip to main content
12,622,517 members (29,233 online)
Click here to Skip to main content
Add your own
alternative version


86 bookmarked

Extended Graphics - An implementation of Rounded Rectangle in C#

, 13 Dec 2003 CC (ASA 2.5)
Rate this:
Please Sign up or sign in to vote.
An implementation of Rounded Rectangle in C# which could be used to create XP-like buttons and rounded border.


Devasted with hours of coding practices and hard-to-design Java applications, I was tempted to try the Microsoft .Net Framework and found C# as a better alternative to Java. Making Windows programs was even easier and I could see endless possibilities for programs on the Windows Platform.

After-effects of this switch left me wondering how I could create graphics on components and forms and I somehow (read: hours of searches on CodeProject and the Framework Documentation) came to the conclusion that the use of Graphics was a necessity in my programs. Meanwhile, CodeProject was flooding with articles on creating XP-like buttons and forms. More specifically, user controls that used rounded paths and ellaborate designs. That's when I decided that I would create a similar button with a Rounded Rectangle. "It's so simple", I thought to myself.


I sat down to create the button myself. Vague images, floated around in my head, of how I would have accomplished this in Java. The most appropriate implementation that I could think of was something like this (Oh! How I loved Java):

import java.awt.*;

// A simple implementation of a drawing with Rounded Rectangle in Java.
// Notice that the Graphics class has methods:
// fillRoundRect and drawRoundRect,
// both having six arguments, the last two being width 
// and height of the round
// curves or arcs.
public class RoundButton extends Canvas
    public RoundButton()
        // Initialization code comes here
        this.setSize(100, 20);

    public void paint(Graphics g)
        // Drawing code comes here
        g.setColor(new Color(200, 200, 200));
        g.fillRoundRect(2, 2, this.getWidth()-4,
          this.getHeight()-4, 5, 5);
        g.setColor(new Color(60, 60, 60));
        g.drawRoundRect(2, 2, this.getWidth()-4,
          this.getHeight()-4, 5, 5);

The Horror

However, as I stepped further to demonstrate the same effect in C#, it was then that I came face-to-face with sudden disbelief. The C# Graphics class that I had praised so much lacked a method for a Rounded Rectangle. What!?! How tedious would it be to create a Rounded Rectangle in such a situation. So, I retreated back to where I had started: searching CodeProject. Though, I found loads of code telling me how this could be implemented but all the codes were built around some user control or component. I wanted a class that would most probably inherit the methods and properties of the Graphics class and include additional and extended functionality. But there was still one problem: The Graphics class was abstract and/or sealed (I don't know why I hate this word).

The Answers

Amidst results on Google [new window], I came across a forum named Drawing Rectangle but with rounded corners... [new window] that lay there, waiting for a desparate soul to encounter it's existence on the Mathew Reynold's .NET 247's Newsgroup [new window]. A certain person, whom I would like to mention here, named Tim Overbay, provided with a little routine to create such a Rounded Rectangle in VB.Net. This was just the starting point I had needed to carry on with my very own implementation. I copied the code, converted it to C# and there I had it. The final result: a class that I now lovingly dub as the ExtendedGraphics class. The complete code is present here as follows.

using System; 
using System.Drawing; 
using System.Drawing.Drawing2D; 

// A simple extension to the Graphics class for extended 
// graphic routines, such, 
// as for creating rounded rectangles. 
// Because, Graphics class is an abstract class, 
// that is why it can not be inherited. Although, 
// I have provided a simple constructor 
// that builds the ExtendedGraphics object around a 
// previously created Graphics object. 
// Please contact: for the most 
// recent implementations of
// this class. 
namespace System.Drawing.Extended 

    /// <SUMMARY> 
    /// Inherited child for the class Graphics encapsulating 
    /// additional functionality for curves and rounded rectangles. 
    /// </SUMMARY> 
    public class ExtendedGraphics 

        private Graphics mGraphics; 
        public Graphics Graphics 
            get{ return this.mGraphics; } 
            set{ this.mGraphics = value; } 

        public ExtendedGraphics(Graphics graphics) 
            this.Graphics = graphics; 

        #region Fills a Rounded Rectangle with integers. 
        public void FillRoundRectangle(System.Drawing.Brush brush, 
          int x, int y,
          int width, int height, int radius) 

            float fx = Convert.ToSingle(x);
            float fy = Convert.ToSingle(y); 
            float fwidth = Convert.ToSingle(width);
            float fheight = Convert.ToSingle(height); 
            float fradius = Convert.ToSingle(radius); 
            this.FillRoundRectangle(brush, fx, fy, 
              fwidth, fheight, fradius); 


        #region Fills a Rounded Rectangle with continuous numbers.
        public void FillRoundRectangle(System.Drawing.Brush brush, 
          float x, float y,
          float width, float height, float radius)
            RectangleF rectangle = new RectangleF(x, y, width, height);
            GraphicsPath path = this.GetRoundedRect(rectangle, radius);
            this.Graphics.FillPath(brush, path);

        #region Draws a Rounded Rectangle border with integers. 
        public void DrawRoundRectangle(System.Drawing.Pen pen, int x, int y,
          int width, int height, int radius) 
            float fx = Convert.ToSingle(x);
            float fy = Convert.ToSingle(y); 
            float fwidth = Convert.ToSingle(width);
            float fheight = Convert.ToSingle(height); 
            float fradius = Convert.ToSingle(radius); 
            this.DrawRoundRectangle(pen, fx, fy, fwidth, fheight, fradius); 

        #region Draws a Rounded Rectangle border with continuous numbers. 
        public void DrawRoundRectangle(System.Drawing.Pen pen, 
          float x, float y,
          float width, float height, float radius) 
            RectangleF rectangle = new RectangleF(x, y, width, height); 
            GraphicsPath path = this.GetRoundedRect(rectangle, radius); 
            this.Graphics.DrawPath(pen, path); 

        #region Get the desired Rounded Rectangle path. 
        private GraphicsPath GetRoundedRect(RectangleF baseRect, 
           float radius) 
            // if corner radius is less than or equal to zero, 
            // return the original rectangle 
            if( radius<=0.0F ) 
                GraphicsPath mPath = new GraphicsPath(); 
                return mPath;

            // if the corner radius is greater than or equal to 
            // half the width, or height (whichever is shorter) 
            // then return a capsule instead of a lozenge 
            if( radius>=(Math.Min(baseRect.Width, baseRect.Height))/2.0) 
              return GetCapsule( baseRect ); 

            // create the arc for the rectangle sides and declare 
            // a graphics path object for the drawing 
            float diameter = radius * 2.0F; 
            SizeF sizeF = new SizeF( diameter, diameter );
            RectangleF arc = new RectangleF( baseRect.Location, sizeF ); 
            GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath(); 

            // top left arc 
            path.AddArc( arc, 180, 90 ); 

            // top right arc 
            arc.X = baseRect.Right-diameter; 
            path.AddArc( arc, 270, 90 ); 

            // bottom right arc 
            arc.Y = baseRect.Bottom-diameter; 
            path.AddArc( arc, 0, 90 ); 

            // bottom left arc
            arc.X = baseRect.Left;     
            path.AddArc( arc, 90, 90 );     

            return path; 

        #region Gets the desired Capsular path. 
        private GraphicsPath GetCapsule( RectangleF baseRect ) 
            float diameter; 
            RectangleF arc; 
            GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath(); 
                if( baseRect.Width>baseRect.Height ) 
                    // return horizontal capsule 
                    diameter = baseRect.Height; 
                    SizeF sizeF = new SizeF(diameter, diameter);
                    arc = new RectangleF( baseRect.Location, sizeF ); 
                    path.AddArc( arc, 90, 180); 
                    arc.X = baseRect.Right-diameter; 
                    path.AddArc( arc, 270, 180); 
                else if( baseRect.Width < baseRect.Height ) 
                    // return vertical capsule 
                    diameter = baseRect.Width;
                    SizeF sizeF = new SizeF(diameter, diameter);
                    arc = new RectangleF( baseRect.Location, sizeF ); 
                    path.AddArc( arc, 180, 180 ); 
                    arc.Y = baseRect.Bottom-diameter; 
                    path.AddArc( arc, 0, 180 ); 
                    // return circle 
                    path.AddEllipse( baseRect ); 
            catch(Exception ex)
                path.AddEllipse( baseRect ); 
            return path; 

What does the code do?

The above code is a simple class that could be used in your projects for additional drawing routines. What I tried to do here is that I created the class that accepts a Graphics class object. Why I did this is a harsher punishment I got because the Graphics class was sealed and it could not be inherited. Otherwise, I would have simply had inherited my class with the Graphics class.

There are two private methods in the class and four public methods. The two private methods namely the GetRoundedRect(...) and the GetCapsule(...) method are of the most importance. Both these methods draw four lines connected with rounded arcs to form a Rounded Rectangle. If the rectangle's height or width is less than the diameter of arc specified, then the method instead of providing the user with a rectangular shape, gives the user a capsule obtained through the GetCapsule(...) method. If both the width and height are less than the diameter or the arc and are of the same size, then a circular ellipse is obtained from the method.

To make the class more useful and familiar, four methods are added to the class that resemble methods found in the Graphics class.

What's Next...

Think of this article as a first in a series of articles, because I would be using this same class in some of my upcoming tutorials on how to create buttons and effective user interface. I would be grateful to anyone who gives me advice on how I could optimize the above code and any suggestions. I am working on an implementation for even-sided polygons and will include those snippets and methods in this class in the near future.


This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License


About the Author

Arun Reginald Zaheeruddin
Software Developer (Senior) Plasmoid Technologies
United Kingdom United Kingdom
Arun Reginald Zaheeruddin is a software developer residing in London. His initial forays into the world of software development began in December 1999 when he first got hooked to Java. He still prefers it over other programming languages. Also with a commercial experience of over eight years in C, C++, C#, Objective-C, VB.Net, Python, Ruby, PHP, HTML, Javascript and CSS, he feels it an honour to share his knowledge about the world of programming with people thinking of wading its waters. In his part time, he does laptop repairs at the Computer & Laptop Centre.

You may also be interested in...


Comments and Discussions

QuestionGood Solution For My Project. Pin
Ehsaan.Crimson1-Jul-15 22:07
memberEhsaan.Crimson1-Jul-15 22:07 
GeneralMy vote of 3 Pin
A.Q.Ghouri28-Apr-14 19:11
memberA.Q.Ghouri28-Apr-14 19:11 
GeneralMy vote of 5 Pin
Hanson Cheng12-Apr-11 12:36
memberHanson Cheng12-Apr-11 12:36 
GeneralMessage Removed Pin
zzylouiskoo20-Apr-10 22:49
memberzzylouiskoo20-Apr-10 22:49 
GeneralRadius calculation Pin
MaxAnarki17-Jul-09 0:08
memberMaxAnarki17-Jul-09 0:08 
GeneralRe: Radius calculation Pin
Arun Reginald24-Jul-09 20:25
memberArun Reginald24-Jul-09 20:25 
GeneralI ported it for CompactFramework on Windows Mobile Pin
Daniel Siegl21-Nov-08 3:17
memberDaniel Siegl21-Nov-08 3:17 
GeneralJust what I was looking for!!! Pin
stinkman18-Sep-08 11:56
memberstinkman18-Sep-08 11:56 
GeneralNicer with extension methods Pin
lazygenius3-Sep-08 1:23
memberlazygenius3-Sep-08 1:23 
GeneralRe: Nicer with extension methods Pin
Arun Reginald24-Jul-09 23:22
memberArun Reginald24-Jul-09 23:22 
QuestionI'am a beginner and don't know how to use graphics, need some help making the code brief Pin
Shimi Weitzhandler18-Feb-08 12:45
memberShimi Weitzhandler18-Feb-08 12:45 
GeneralYour solution is perfect, but too complex PinPopular
kzerza19-Apr-07 0:28
memberkzerza19-Apr-07 0:28 

Why you create new ExtendedGraphics class, just only for RoundRectangle drawing?

Stock Graphics has DrawPath and FillPath. It is ALL YOU NEED!

So, my example:
public class ExtendedPrimitives

public static GraphicsPath RoundRect(int x, int y,
int width, int height,
int radius, int lw)
// x,y - top left corner of rounded rectangle
// width, height - width and height of round rect
// radius - radius for corners
// lw - line width (for Graphics.Pen)

GraphicsPath g = new GraphicsPath();
int diameter = radius*2;
return g;


// many other path-based primitives
// ...

We have an ideal rounded rectangle

So, draw it:

// assuming, what g is already bound variable, type of
// System.Drawing.Graphics
GraphicsPath rrect = ExtendedPrimitives.RoundRect(100,100,100,130,3);
g.DrawPath(new Pen(System.Drawing.Color.Navy,3),rrect);
// or FillPath, if it needed

GeneralRe: Your solution is perfect, but too complex Pin
Michael90008-Jun-07 9:38
memberMichael90008-Jun-07 9:38 
GeneralRe: Your solution is perfect, but too complex Pin
Arun Reginald24-Jul-09 20:22
memberArun Reginald24-Jul-09 20:22 
GeneralRe: Your solution is perfect, but too complex Pin
Michael900025-Aug-09 6:35
memberMichael900025-Aug-09 6:35 
GeneralFigure is not perferct Pin
e1e0n30-Jan-07 10:57
membere1e0n30-Jan-07 10:57 
GeneralRe: Figure is not perferct Pin
shihyi12-Feb-07 22:18
membershihyi12-Feb-07 22:18 
GeneralRe: Figure is not perferct Pin
Seishin#16-Jun-07 0:34
memberSeishin#16-Jun-07 0:34 
GeneralThanks for mentioning me! Pin
LuharVB25-Apr-06 7:48
memberLuharVB25-Apr-06 7:48 
GeneralRe: Thanks for mentioning me! Pin
Arun Reginald25-Apr-06 23:27
memberArun Reginald25-Apr-06 23:27 
NewsBetter GetRoundedRect : PinPopular
Gooom30-Jan-06 6:27
memberGooom30-Jan-06 6:27 
GeneralRe: Better GetRoundedRect : Pin
burning snow20-Jun-07 23:47
memberburning snow20-Jun-07 23:47 
GeneralRe: Better GetRoundedRect : Pin
Dana LeBeau18-Mar-08 16:27
memberDana LeBeau18-Mar-08 16:27 
GeneralRe: Better GetRoundedRect : Pin
vjedlicka9-Nov-08 10:26
membervjedlicka9-Nov-08 10:26 
GeneralRe: Better GetRoundedRect : better yet + bug fixes Pin
Brian Perrin18-Feb-09 18:21
memberBrian Perrin18-Feb-09 18:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.161128.1 | Last Updated 14 Dec 2003
Article Copyright 2003 by Arun Reginald Zaheeruddin
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid