|
Simple, functional, and easy to use.
Two thumbs up
the only additions I would make is
#region "Added Rectangles"
public void DrawRoundRectangle(System.Drawing.Pen pen, Rectangle rec, int radius)
{
this.DrawRoundRectangle(pen, rec.X, rec.Y, rec.Width, rec.Height, radius);
}
public void FillRoundRectangle(System.Drawing.Brush brush, Rectangle rec, int radius)
{
this.FillRoundRectangle(brush, rec.X, rec.Y, rec.Width, rec.Height, radius);
}
#endregion
Just added the ability to use rects - saves some typing
|
|
|
|
|
I would be adding some extra functionality to the class and would require ideas and requirements from the readers. I'll also try to include some examples and screenshots alongwith the code in the article. Please wait a while, for there's more to come.
The beginning of knowledge is the fear of God
|
|
|
|
|
Support for X and Y radii. I think this will make it complete.
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Thank a lot at this:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace RoundRect
{
public sealed class ExtendedGraphics
{
#region Constructors and Destructor
private ExtendedGraphics()
{
}
#endregion
#region Public Methods
public static void FillRoundRectangle(Graphics g, Brush brush, int x, int y,
int width, int height, int radiusX, int radiusY)
{
FillRoundRectangle(g, brush, (float)x, (float)y,
(float)width, (float)height, (float)radiusX, (float)radiusY);
}
public static void FillRoundRectangle(Graphics g, Brush brush, float x, float y,
float width, float height, float radiusX, float radiusY)
{
if (g != null)
{
RectangleF rectangle = new RectangleF(x, y, width, height);
GraphicsPath path = GetRoundedRect(rectangle, radiusX, radiusY);
g.FillPath(brush, path);
}
}
public static void DrawRoundRectangle(Graphics g, Pen pen, int x, int y,
int width, int height, int radiusX, int radiusY)
{
DrawRoundRectangle(g, pen, (float)x, (float)y, (float)width,
(float)height, (float)radiusX, (float)radiusY);
}
public static void DrawRoundRectangle(Graphics g, Pen pen, float x, float y,
float width, float height, float radiusX, float radiusY)
{
if (g != null)
{
RectangleF rectangle = new RectangleF(x, y, width, height);
GraphicsPath path = GetRoundedRect(rectangle, radiusX, radiusY);
g.DrawPath(pen, path);
}
}
#endregion
#region Private Methods
private static GraphicsPath GetRoundedRect(RectangleF baseRect,
float radiusX, float radiusY)
{
if (radiusX <= 0.0F || radiusY <= 0.0F)
{
GraphicsPath mPath = new GraphicsPath();
mPath.AddRectangle(baseRect);
mPath.CloseFigure();
return mPath;
}
if (radiusX >= (Math.Min(baseRect.Width, baseRect.Height)) / 2.0)
return GetCapsule(baseRect);
if (radiusY >= (Math.Min(baseRect.Width, baseRect.Height)) / 2.0)
return GetCapsule(baseRect);
float diameterX = radiusX * 2.0F;
float diameterY = radiusY * 2.0F;
SizeF sizeF = new SizeF(diameterX, diameterY);
RectangleF arc = new RectangleF(baseRect.Location, sizeF);
GraphicsPath path = new GraphicsPath();
path.AddArc(arc, 180, 90);
arc.X = baseRect.Right - diameterX;
path.AddArc(arc, 270, 90);
arc.Y = baseRect.Bottom - diameterY;
path.AddArc(arc, 0, 90);
arc.X = baseRect.Left;
path.AddArc(arc, 90, 90);
path.CloseFigure();
return path;
}
private static GraphicsPath GetCapsule(RectangleF baseRect)
{
GraphicsPath path = new GraphicsPath();
try
{
if (baseRect.Width > baseRect.Height)
{
float diameter = baseRect.Height;
SizeF sizeF = new SizeF(diameter, diameter);
RectangleF 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)
{
float diameter = baseRect.Width;
SizeF sizeF = new SizeF(diameter, diameter);
RectangleF arc = new RectangleF(baseRect.Location, sizeF);
path.AddArc(arc, 180, 180);
arc.Y = baseRect.Bottom - diameter;
path.AddArc(arc, 0, 180);
}
else
{
path.AddEllipse(baseRect);
}
}
catch
{
path.AddEllipse(baseRect);
}
finally
{
path.CloseFigure();
}
return path;
}
#endregion
}
}
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
With this sample:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace RoundRect
{
public class MainForm : System.Windows.Forms.Form
{
private ExtendedGraphics m_objGraphics;
private System.ComponentModel.Container components = null;
public MainForm()
{
InitializeComponent();
m_objGraphics = new ExtendedGraphics();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
this.BackColor = System.Drawing.SystemColors.Window;
this.ClientSize = new System.Drawing.Size(568, 494);
this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "RoundRect Test";
this.Resize += new System.EventHandler(this.OnResize);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnMouseDown);
this.Load += new System.EventHandler(this.OnLoad);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.OnPaint);
}
#endregion
[STAThread]
static void Main()
{
Application.Run(new MainForm());
}
private void OnLoad(object sender, System.EventArgs e)
{
}
private void OnPaint(object sender, System.Windows.Forms.PaintEventArgs e)
{
m_objGraphics.Graphics = e.Graphics;
Rectangle rectClient = this.ClientRectangle;
rectClient.Inflate(-rectClient.Width/8, -rectClient.Height/8);
Color penColor = Color.FromArgb(64, Color.Blue);
Pen pen = new Pen(penColor, 4f);
int radiusX = rectClient.Width/4;
int radiusY = rectClient.Height/4;
e.Graphics.DrawRectangle(Pens.Green, rectClient);
m_objGraphics.DrawRoundRectangle(pen, rectClient.X, rectClient.Y,
rectClient.Width, rectClient.Height, radiusX, radiusY);
pen.Dispose();
Rectangle rcTL = new Rectangle(rectClient.Left, rectClient.Top,
radiusX * 2, radiusY * 2);
e.Graphics.DrawEllipse(Pens.Red, rcTL);
Rectangle rcBL = new Rectangle(rectClient.Left,
rectClient.Bottom - radiusY * 2,
radiusX * 2, radiusY * 2);
e.Graphics.DrawEllipse(Pens.Red, rcBL);
Rectangle rcTR = new Rectangle(rectClient.Right - radiusX * 2,
rectClient.Top,
radiusX * 2, radiusY * 2);
e.Graphics.DrawEllipse(Pens.Red, rcTR);
Rectangle rcBR = new Rectangle(rectClient.Right - radiusX * 2,
rectClient.Bottom - radiusY * 2,
radiusX * 2, radiusY * 2);
e.Graphics.DrawEllipse(Pens.Red, rcBR);
m_objGraphics.Graphics = null;
}
private void OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
}
private void OnResize(object sender, System.EventArgs e)
{
Invalidate();
}
}
}
When you try resizing the form, sometimes the corner ellipses are not aligned correctly with round rectangle. Is there any possible improvement?
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
|
|
|
|
|
Just an annoyance, but I hate compiler warnings, if you dont plan on using the exception details don't specify them. Nice code though.
Change the following:
catch (Exception ex)
{
path.AddEllipse(baseRect);
}
to:
catch (Exception)
{
path.AddEllipse(baseRect);
}
|
|
|
|
|
Thanks for the comment. I'll fix the code once I'm finished with the Earthquake disaster relief-work here in Pakistan. I do, nevertheless, appreciate your feedback. I know I have to clean up the whole code and more yet the article itself.
The beginning of knowledge is the fear of God
|
|
|
|
|
Hi,
First of all, thanks for the great code. I'm wondering if it also works in web forms too.
I've compiled your code into a DLL libary in the "root\bin" directory of my web site, and I'm referencing it using the "using" directive (using System.Drawing.Extended;). For some reason it doesn't work.
I can do the following:
SolidBrush bsh = new SolidBrush( Color.FromArgb( 128, 0, 0, 0 ) );
Graphics test;
test = Graphics.FromImage( OutputImage );
test = this.CreateGraphics();
test.FillRectangle( bsh, 5, 5, 25, 25 );
Which gives me a semi transparent rectangle over the top of an image, but when I try and use:
test.FillRoundRectangle( bsh, 5, 5, 25, 25, 5 );
I get the following error:
Compiler Error Message: CS0117: 'System.Drawing.Graphics' does not contain a definition for 'FillRoundRectangle'
Any suggestions on how to get it working?
Thanks.
- Nic -
|
|
|
|
|
You need to first instanciate an object of ExtendedGraphics, passing in your current form's graphics object.
SolidBrush bsh = new SolidBrush( Color.FromArgb( 128, 255, 0, 0 ) );
ExtendedGraphics eg = new ExtendedGraphics(this.CreateGraphics());
eg.FillRoundRectangle( bsh,5, 5, 50, 25, 3 );
Voila!...er, except for one thing.. He has a bug in his class and it doesn't complete the bottom right arc of the rounded rectangle.
Regards,
Jason J.
|
|
|
|
|
I'm drawing a shaped control using a version of the following code in the OnPaint:
GraphicsPath path = new GraphicsPath();
path.AddRectangle(rect); // rect is previously defined
Region region = new Region(path);
Pen penOutline = new Pen(Color.Black, 1.0f);
e.Graphics.DrawPath(penOutline, path);
I ALWAYS lose the right and bottom portions of the outline. For a rectangle, it's easy for me to compensate for this by doing a DrawLine to draw the right & bottom sides. However, I'll be using your RoundedRectangle example to render other shapes, so trying to draw in the "right" and "bottom" sides won't be a viable alternative.
I've tried playing with different Pen.Alignment values as well, but that hasn't helped.
Why is this happening and how can I get around it?
Thanks in advance!
|
|
|
|
|
I love your code....you got my 5......I need that functionality absolutely. Could I use it in my commercial applications?
|
|
|
|
|
Thankyou for your nice comment. I am flattered. You definitely can have the code and use it in Commercial Applications, but it would be better to address the copyright details when you use the code.
And oh... I almost forgot. I have done some more work on the class which includes some Graphics bitting/buffering and some P/Invoke for some native functionalities. If you need the newer version, please do tell me. I will try reposting my work here.
The beginning of knowledge is the fear of God
|
|
|
|
|
hi!
i enjoyed the article and am also currently creating dynamic UI element libraries for my website.
i discovered a simple, two-step routine to create a rectangle or capsule button or concievably any convex polygon.
first stage is to define a graphics path and add an ellipse.
then, instead of filling the entire figure, fill an overlapping rectangle, whose corners fall between the ellipses bounding rectangle and the ellipses border.
remember, the path gradient does not fill outside its path.
if you play around with the geometry, you should get a nice rounded or capsule effect...
see Creating a Path Gradient in the GDI+ section of MSDN for more details.
Heres the sample code:
// Create a path that consists of a single ellipse.
GraphicsPath path;
path.AddEllipse(0, 0, 140, 70);
// Use the path to construct a brush.
PathGradientBrush pthGrBrush(&path);
// Set the color at the center of the path to blue.
pthGrBrush.SetCenterColor(Color(255, 0, 0, 255));
// Set the color along the entire boundary of the path to aqua.
Color colors[] = {Color(255, 0, 255, 255)};
int count = 1;
pthGrBrush.SetSurroundColors(colors, &count);
graphics.FillEllipse(&pthGrBrush, 0, 0, 140, 70);
Et versus digitos habet.
luckydon@tokyo.com
|
|
|
|
|
oops!
instead of
graphics.FillEllipse(&pthGrBrush, 0, 0, 140, 70);
change to
graphics.FillRectangle(&pthGrBrush, 5, 5, 130, 60)
sorry for the mixup...
Et versus digitos habet.
luckydon@tokyo.com
|
|
|
|
|
Hello,
Nice article, looking forward to the next one. Anyone frustrated with System.Drawing might want to play with VG.net. Send a beta request using the email in my sig. VG.net has a graphics designer integrated in VS.net and you can animate in real time by changing object properties. You can create rounded rects in the designer by dragging the mouse. The runtime will be free, and we will have special design-time licenses for students/freeware/open source authors.
I hope this post isn't too "spammy". Just trying to get some beta testers.
Regards,
Frank Hileman
check out VG.net: www.vgdotnet.com
An animated vector graphics system integrated in VS.net
beta requests: beta at vgdotnet.com
|
|
|
|
|
Don't show this massive implementation to anybody that has used the Pet Shop to suggest that developing in Java is verbose when compared to using the DNF. This example clearly shows there are circumstances where the DNF remains to be refined. Likely 2.0. Right?
<%= clintonG
|
|
|
|
|
I guess we can wait until that happens?!?
The beginning of knowledge is the fear of God
|
|
|
|
|
|
The article was written at a time when Microsoft was thinking of including J# in its .Net product lineup. If J# would have been around, there would have been no need to write the article (The comment also dates from then).
BTW, your article on the MSDN magazine was a great work indeed. I was teaching my students the benefits of using J# over C# and Sun's Java Environment and your article helped a lot.
The beginning of knowledge is the fear of God
|
|
|
|
|
...Might increase the article's appeal.
*¨¨`)
¸¸.·´ ¸.·*¨¨`)
(¸¸.·* ¸ .·*
¸¸.·*
(¸¸.~~> Joel Holdsworth.
|
|
|
|
|
I am in the process of writing an article that uses this class to create a simple, attractive and effective button. I believe that you definitely will love the upcoming article. Be sure to check it out. It will include a screenshot with complete illustrations on how to accomplish each step. Anyways, thanks for notifying.
The beginning of knowledge is the fear of God
|
|
|
|
|
I have been getting nice comments on the code above, since I posted this article and a number of good votes as well. What I would like to encourage the users of is that they should also include comments in this article's discussion board, so that I might be able to know what this code lacks and what makes this article so good. Anyways, thanks to all the people who have been so content with this article and had voted for it. I don't know what was more overwhelming: Saddam being caught or this article being voted the best. Thanks guys.
I will be adding a simple Custom User Control that will show how you can use this class above in your project to create a simple XP-like button. So stay tuned for more surprises coming your way.
The beginning of knowledge is the fear of God
|
|
|
|
|