Code:
private void picCanvas_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
DrawRndRect(ref e);
}
/// <summary>
/// Draws and Fills a Rounded Rectangle and it's accompanying shadow
/// </summary>
/// <param name="e">PaintEventArgs object passed in from the Picturebox</param>
private void DrawRndRect(ref PaintEventArgs e)
{
// I like clean lines so set the smoothingmode to Anti-Alias
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
// lets create a rectangle that will be centered in the picturebox and
// just under half the size
Rectangle _Rectangle = new Rectangle((int)(picCanvas.Width * .3), (int)(picCanvas.Height * .3),
(int)(picCanvas.Width * .4), (int)(picCanvas.Height * .4));
// create the radius variable and set it equal to 20% the height of the rectangle
// this will determine the amount of bend at the corners
float _Radius = (int)(_Rectangle.Height * .2);
// create an x and y variable so that we can reduce the length of our code lines
float X = _Rectangle.Left;
float Y = _Rectangle.Top;
// make sure that we have a valid radius, too small and we have a problem
if(_Radius < 1)
_Radius = 1;
try
{
// Create a graphicspath object with the using operator so the framework
// can clean up the resources for us
using(GraphicsPath _Path = new GraphicsPath())
{
// build the rounded rectangle starting at the top line and going around
// until the line meets itself again
_Path.AddLine(X + _Radius, Y, X + _Rectangle.Width - (_Radius * 2), Y);
_Path.AddArc(X + _Rectangle.Width - (_Radius * 2), Y, _Radius * 2, _Radius * 2, 270, 90);
_Path.AddLine(X + _Rectangle.Width, Y + _Radius, X + _Rectangle.Width, Y + _Rectangle.Height - (_Radius * 2));
_Path.AddArc(X + _Rectangle.Width - (_Radius * 2), Y + _Rectangle.Height - (_Radius * 2), _Radius * 2, _Radius * 2,0,90);
_Path.AddLine(X + _Rectangle.Width - (_Radius * 2), Y + _Rectangle.Height, X + _Radius, Y + _Rectangle.Height);
_Path.AddArc(X, Y + _Rectangle.Height - (_Radius * 2), _Radius * 2, _Radius * 2, 90, 90);
_Path.AddLine(X, Y + _Rectangle.Height - (_Radius * 2), X, Y + _Radius);
_Path.AddArc(X, Y, _Radius * 2, _Radius * 2, 180, 90);
// this is where we create the shadow effect, so we will use a
// pathgradientbursh
using(PathGradientBrush _Brush = new PathGradientBrush(_Path))
{
// set the wrapmode so that the colors will layer themselves
// from the outer edge in
_Brush.WrapMode = WrapMode.Clamp;
// Create a color blend to manage our colors and positions and
// since we need 3 colors set the default length to 3
ColorBlend _ColorBlend = new ColorBlend(3);
// here is the important part of the shadow making process, remember
// the clamp mode on the colorblend object layers the colors from
// the outside to the center so we want our transparent color first
// followed by the actual shadow color. Set the shadow color to a
// slightly transparent DimGray, I find that it works best.
_ColorBlend.Colors = new Color[]{Color.Transparent,
Color.FromArgb(180, Color.DimGray),
Color.FromArgb(180, Color.DimGray)};
// our color blend will control the distance of each color layer
// we want to set our transparent color to 0 indicating that the
// transparent color should be the outer most color drawn, then
// our Dimgray color at about 10% of the distance from the edge
_ColorBlend.Positions = new float[]{0f, .1f, 1f};
// assign the color blend to the pathgradientbrush
_Brush.InterpolationColors = _ColorBlend;
// fill the shadow with our pathgradientbrush
e.Graphics.FillPath(_Brush, _Path);
}
// since the shadow was drawm first we need to move the actual path
// up and back a little so that we can show the shadow underneath
// the object. To accomplish this we will create a Matrix Object
Matrix _Matrix = new Matrix();
// tell the matrix to move the path up and back the designated distance
_Matrix.Translate(_ShadowDistance, _ShadowDistance);
// assign the matrix to the graphics path of the rounded rectangle
_Path.Transform(_Matrix);
// fill the graphics path first
using(LinearGradientBrush _Brush = new LinearGradientBrush(
picCanvas.ClientRectangle,Color.Tomato, Color.MistyRose, LinearGradientMode.Vertical))
{
e.Graphics.FillPath(_Brush, _Path);
}
// Draw the Graphicspath last so that we have cleaner borders
using(Pen _Pen = new Pen(Color.DimGray, 1f))
{
e.Graphics.DrawPath(_Pen, _Path);
}
}
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine(GetType().Name + ".DrawRndRect() Error: " + ex.Message);
}
}