Reputation: 3611
Im trying to get a usercontrol to act as a progressbar. As far as i am aware, i need to draw a new bar ontop of the old one and increase its size according to the percentage completed. I have the following code, but unfortunately the green bar is at 100% even though i set the percentage property to 0% when the control is initialized. Im assuming i have made a dumb oversight but i cant see it, any help would be appreciated. Thanks.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace CustomPbar
{
public partial class Pbar : UserControl
{
private int PercentageValue;
public int Percentage
{
get { return PercentageValue;}
set
{
PercentageValue = value;
this.Invalidate();
}
}
public Pbar()
{
InitializeComponent();
Percentage = 0;
using(GraphicsPath path = new GraphicsPath())
{
path.StartFigure();
// top left arc
path.AddArc(0, 0, (10), (10), 180, 90);
//rect, 180, 90);
// top right arc
path.AddArc(((this.Width) - (10)), 0, (10), (10), 270, 90);
// bottom right arc
path.AddArc(((this.Width) - (10)), ((this.Height) - (10)), (10), (10), 0, 90);
// bottom left arc
path.AddArc(0, ((this.Height) - (10)), (10), (10), 90, 90);
path.CloseFigure();
this.Region = new Region(path);
this.BackColor = SystemColors.ControlLight;
this.BackgroundImage = new Bitmap(@"c:\users\FrazMan\Desktop\pb1.bmp");
this.BackgroundImageLayout = ImageLayout.Stretch;
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Rectangle rect = new Rectangle(0, 0, ((this.Width)*((Percentage)/100)), this.Height);
using (GraphicsPath gp = new GraphicsPath())
{
gp.StartFigure();
// top left arc
gp.AddArc(0, 0, (10), (10), 180, 90);
// top right arc
gp.AddArc(((rect.Width) - (10)), 0, (10), (10), 270, 90);
// bottom right arc
gp.AddArc(((rect.Width) - (10)), ((rect.Height) - (10)), (10), (10), 0, 90);
// bottom left arc
gp.AddArc(0, ((rect.Height) - (10)), (10), (10), 90, 90);
gp.CloseFigure();
SolidBrush greenBrush = new SolidBrush(Color.Green);
e.Graphics.FillPath(greenBrush, gp);
greenBrush.Dispose();
}
using(Graphics Draw = this.CreateGraphics())
{
Draw.DrawString(Percentage.ToString() + "%", ProgressBar.DefaultFont, Brushes.Black, new PointF((this.Width / 2) - ((Draw.MeasureString(Percentage.ToString() + "%", ProgressBar.DefaultFont)).Width / 2.0F),
(this.Height / 2) - ((Draw.MeasureString(Percentage.ToString() + "%", ProgressBar.DefaultFont)).Height / 2.0F)));
}
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.Refresh();
}
}
}
Upvotes: 1
Views: 2907
Reputation: 44326
Several places you create a Rectangle
, but never use it. I think you want to use the rect
width and height instead of this
width and height.
You should also be using e.Graphics
instead of this.CreateGraphics()
for drawing the percentage string.
There is a large amount of duplicate code, and I recommend you keep all drawing code in OnPaint
and when you want to redraw, call this.Refresh()
. It will help a lot with maintenance.
Upvotes: 1
Reputation: 8852
here is my take on custom progressbar in c#
I have % notches also, but you can get rid of them easily. works pretty good
ProgressBarExtended.cs
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace PressdMonitorSrvMod.Custom_Control
{
public partial class ProgressBarExtended : UserControl
{
//constructor
public ProgressBarExtended()
{
InitializeComponent();
}
#region Properties
// Create a Value property for the Progress bar
public float Value
{
get { return percent; }
set
{
// Maintain the Value between 0 and 100
if (value < 0) value = 0;
else if (value > 100) value = 100;
percent = value;
percentage.Text = string.Format("{0}%", value);
//change the notch color when overdrawn
if (value.Equals(25f))
notch25.BackColor = Color.White;
else if (value.Equals(50f))
notch50.BackColor = Color.White;
else if (value.Equals(75f))
notch75.BackColor = Color.White;
else if (value > 0 && value < 25)
notch25.BackColor = notch50.BackColor = notch75.BackColor = ProgressBarColor;
else if (value > 25 && value < 50)
notch50.BackColor = notch75.BackColor = ProgressBarColor;
else if (value > 50 && value < 75)
notch75.BackColor = ProgressBarColor;
//move the percentage text to the center from start
if (percentage.Location.X < ((Width - percentage.Width)/2))
{
percentage.Location = new Point((int) ((percent/100)*Width) - percentage.Width, 0);
percentage.Margin = new Padding(0);
percentage.Dock = DockStyle.None;
percentage.BorderStyle = BorderStyle.None;
percentage.AutoSize = true;
percentage.TextAlign = ContentAlignment.BottomCenter;
}
else
{
//already in center, keep it in center
ProgressBarExtendedSizeChanged();
}
//redraw after changes
Refresh();
}
}
public Color ProgressBarColor { get; set; }
public Color HighlightColor { get; set; }
public Font LabelFont
{
get { return percentage.Font; }
set { percentage.Font = value; }
}
public Color LabelColor
{
get { return percentage.ForeColor; }
set { percentage.ForeColor = value; }
}
//make it readonly, hide the property
public new BorderStyle BorderStyle;
#endregion Properties
#region Events
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.HighSpeed;
// Create a brush that will draw the background of the Progress bar
using (var brush = new SolidBrush(ProgressBarColor))
{
using (var pen = new Pen(brush))
{
// Create a linear gradient that will be drawn over the background.
using (var lgBrush = new LinearGradientBrush(new Rectangle(-1, -1, Width, Height),
Color.FromArgb(150, highlightColor),
Color.FromArgb(10, ProgressBarColor),
LinearGradientMode.Vertical))
{
// Calculate how much has the Progress bar to be filled for "x" %
var width = (int)((percent / 100) * Width);
//draw the progress bar
e.Graphics.FillRectangle(brush, 0, 0, width, Height);
e.Graphics.FillRectangle(lgBrush, 0, 0, width, Height);
//draw the border
e.Graphics.DrawRectangle(pen, 0, 0, Width - 1, Height - 1);
}
}
}
}
private void ProgressBarExtendedSizeChanged()
{
// Maintain the label in the center of the Progress bar
percentage.Location = new Point(Width/2 - percentage.Width/2, 0);
}
#endregion Helper Methods
}
}
Upvotes: 0
Reputation: 1819
In your OnPaint
method, you are using Graphics.FillPath
which will fill in the entire space inside the GraphicsPath
you are creating. Try using Graphics.DrawPath
if you want to just draw the outline of the shape.
Upvotes: 0