Click here to Skip to main content
Licence 
First Posted 15 Feb 2002
Views 73,519
Bookmarked 28 times

GDI+ RoundedRect

By | 15 Feb 2002 | Article
Providing a RoundedRect function for GDI+

Sample Image - Screenshot.jpg

Introduction

Although GDI+ is a very exciting extension to GDI, for some reason, the RoundedRect function is not provided. Although it is obviously possible to use GDI functions with GDI+, this does not give us the ability to use new features such as texturing and alpha transparency with our rounded rectangles. Luckily, GDI+ offers the GraphicsPath class, which we can use to create any shape and then draw using any brush. I've provided a function which can be added to any project, and used as shown to draw a rounded rect, and provided a demo application that allows setting the rounding percentage via a slider. It's quick and dirty ( it's late here ), but it is adequate to show off what the function does. The function is as follows:

GraphicsPath* MakeRoundRect(Point topLeft, Point bottomRight, INT percentageRounded)
{
          ASSERT (percentageRounded >= 1 && percentageRounded <= 100);

          INT left  = min(topLeft.X, bottomRight.X);
          INT right = max(topLeft.X, bottomRight.X);

          INT top    = min(topLeft.Y, bottomRight.Y);
          INT bottom = max(topLeft.Y, bottomRight.Y);

          INT offsetX = (right-left)*percentageRounded/100; 
          INT offsetY = (bottom-top)*percentageRounded/100;

          GraphicsPath pt;
          GraphicsPath * path = pt.Clone();

          path->AddArc(right-offsetX, top, offsetX, offsetY, 270, 90);

          path->AddArc(right-offsetX, bottom-offsetY, offsetX, offsetY, 0, 90);

          path->AddArc(left, bottom - offsetY, offsetX, offsetY, 90, 90);

          path->AddArc(left, top, offsetX, offsetY, 180, 90);

          path->AddLine(left + offsetX, top, right - offsetX/2, top);

          return path;
}

The interesting thing to note is that since I first wrote this code, the ability to call new for GraphicsPath has been removed in some cunning manner ( try it and see ). Instead I must make a local object, and call it's 'Clone' method. It's entirely possible I am just missing something at this late hour, but it seems in line with other classes in GDI+, that you need to create new objects via pointers using GDI+ methods instead of new, and I presume this is because the other .NET languages do not offer pointers.

That's about all there is to it. This code has one flaw - it is poor design that the function creates an object, and the caller must delete it. However, GDI+ kindly does not allow us to return the path as an object, only as a pointer. I'm guessing this has something to do with GDI+ returning every class as a reference, but I am not sure. For some fun, I recommend you play with other things you can add to this path – the Warp method looks like it could especially be a lot of fun.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Christian Graus

Software Developer (Senior)

Australia Australia

Member

Programming computers ( self taught ) since about 1984 when I bought my first Apple ][. Was working on a GUI library to interface Win32 to Python, and writing graphics filters in my spare time, and then building n-tiered apps using asp, atl and asp.net in my job at Dytech. After 4 years there, I've started working from home, at first for Code Project and now for a vet telemedicine company. I owned part of a company that sells client education software in the vet market, but we sold that and now I work for the new owners.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralSmall fix PinmemberTonyTop10:17 1 Apr '05  
To make the code suitable to any type of rectangle, replace
 
INT offsetX = (right-left)*percentageRounded/100;
INT offsetY = (bottom-top)*percentageRounded/100;

 
with

INT minDef = min((right-left), (bottom-top));
 
INT offsetX = minDef*percentageRounded/100;
INT offsetY = minDef*percentageRounded/100;


Generalconfining image to area... Pinmembermliss18:03 20 Sep '03  
QuestionHow to use "new" keyword in VC++6.0 PinsussEnde19:05 27 Oct '02  
AnswerRe: How to use "new" keyword in VC++6.0 PinmemberChristian Graus19:09 27 Oct '02  
GeneralRe: How to use "new" keyword in VC++6.0 Pinmemberende620:31 27 Oct '02  
GeneralRe: How to use "new" keyword in VC++6.0 PinmemberDavide Calabro4:29 12 Jun '03  
GeneralLast Line Pokes Out PinmemberSwinefeaster22:14 2 Aug '02  
GeneralAvoid returning a pointer PinmemberSwinefeaster1:26 2 Aug '02  
GeneralRe: Avoid returning a pointer PinmemberChristian Graus1:43 2 Aug '02  
GeneralRe: Avoid returning a pointer PinmemberSwinefeaster1:46 2 Aug '02  

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

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120528.1 | Last Updated 16 Feb 2002
Article Copyright 2002 by Christian Graus
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid