Introduction
Progress disk is a simple control that I wrote after I saw the one in SQL Server 2005. It can be used to replace the old progress bar with a nice and colorful mix of gradient colors.
Idea
The .NET 2.0 class library has the Graphics object, which is responsible for drawing 2D shapes. It has primitive shapes such as point, line, rectangle, ellipse, pie, etc. I used the DrawPie method to draw my control, which is formed by drawing 3 pie layers over top of each other:
- The first layer in the bottom: a pie having a start angle of zero and a sweep angle of 360 degrees to draw a full circle that serves as the background of the control
- The second layer in the middle: a pie that represent the blocks of the disk; 12 blocks (pie pieces) have been drawn, each having a sweep angle of 25 degrees and a separating angle of 5
- The third layer in the top: similar to the first layer, but its function is to control the size of the blocks; the smaller the circle drawn, the bigger the blocks appear (i.e. having an inner circle with radius zero would give blocks having the shape of slices of a pizza)
Colors
I used a linear gradient brush to fill in the blocks: 2 colors for the inactive blocks and 2 for the active block. Properties added to keep the control flexible include:
Value
: The current value of the progress disk BackGroundColor
: The color of the background ActiveForeColor1
& ActiveForeColor2
: These 2 for the block of current value InactiveForeColor1
& ActiveForeColor2
: These 2 for the rest of the blocks SquareSize
: The side length of the square containing the control BlockSize
: An enum for 6 different sizes SliceNumber
: The number of slices in the control (added by Coyotelapa)
Code
4 GraphicsPath objects were used to draw the control, one for each layer and an extra one to color the block with the current value.
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
region = new Region(ClientRectangle);
if (backGrndColor == Color.Transparent)
{
region.Exclude(bkGroundPath2);
Region = region;
}
e.Graphics.FillPath(new SolidBrush(backGrndColor), bkGroundPath1);
e.Graphics.FillPath(
new LinearGradientBrush(new Rectangle(0, 0, size, size),
inactiveforeColor1, inactiveforeColor2,
value * 360 / 12, true), valuePath);
e.Graphics.FillPath(
new LinearGradientBrush(new Rectangle(0, 0, size, size),
activeforeColor1, activeforeColor2,
value * 360 / 12, true), freGroundPath);
e.Graphics.FillPath(new SolidBrush(backGrndColor), bkGroundPath2);
base.OnPaint(e);
}
private void Render()
{
bkGroundPath1.Reset();
bkGroundPath2.Reset();
valuePath.Reset();
freGroundPath.Reset();
bkGroundPath1.AddPie(new Rectangle(0, 0, size, size), 0, 360);
if (sliceCount == 0)
{
sliceCount = 12;
}
float sliceAngle = 360 / sliceCount;
float sweepAngle = sliceAngle - 5;
for (int i = 0; i < sliceCount; i++)
{
if (value != i)
{
valuePath.AddPie(0, 0, size, size, i * sliceAngle,
sweepAngle);
}
}
bkGroundPath2.AddPie(
(size / 2 - size * blockRatio), (size / 2 - size * blockRatio),
(blockRatio * 2 * size), (blockRatio * 2 * size), 0, 360);
freGroundPath.AddPie(new Rectangle(0, 0, size, size),
value * sliceAngle, sweepAngle);
Invalidate();
}
History
- 16 July, 2006 - Original version posted
- 29 July, 2006 - Updated after adding improvements made by Coyotelapa and fixing some bugs
- 31 May, 2007 - Article edited and moved to the main CodeProject.com article base