using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Text; using System.Windows.Forms; using System.Drawing; using System.Globalization; using Demo.WindowsForms.Properties; using System.Drawing.Drawing2D; namespace BSE.Windows.Forms { /// /// Represents a Windows progress bar control. /// /// Copyright © 2008 Uwe Eichkorn /// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY /// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE /// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR /// PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER /// REMAINS UNCHANGED. /// [ToolboxBitmap(typeof(System.Windows.Forms.ProgressBar))] public partial class ProgressBar : Control { #region Events /// /// Occurs when the value of the BorderColor property changes. /// [Description("Occurs when the value of the BorderColor property is changed on the control.")] public event EventHandler BorderColorChanged; /// /// Occurs when the value of the BackgroundColor property changes. /// [Description("Occurs when the value of the BackgroundColor property is changed on the control.")] public event EventHandler BackgroundColorChanged; /// /// Occurs when the value of the ValueColor property changes. /// [Description("Occurs when the value of the ValueColor property is changed on the control.")] public event EventHandler ValueColorChanged; #endregion #region FieldsPrivate private Color m_backgroundColor; private Color m_valueColor; private Color m_borderColor; private int m_iMinimum; private int m_iMaximum; private int m_iValue; #endregion #region Properties /// /// Gets or sets the color used for the background rectangle of this control. /// /// /// Type: /// A Color used for the background rectangle of this control. /// [Browsable(true)] [Description("The color used for the background rectangle of this control.")] public Color BackgroundColor { get { return this.m_backgroundColor; } set { if (this.m_backgroundColor != value) { this.m_backgroundColor = value; OnBackgroundColorChanged(this, EventArgs.Empty); } } } /// /// Gets or sets the color used for the value rectangle of this control. /// /// /// Type: /// A Color used for the value rectangle of this control. /// [Browsable(true)] [Description("The color used for the value rectangle of this control.")] public Color ValueColor { get { return this.m_valueColor; } set { if (this.m_valueColor != value) { this.m_valueColor = value; OnValueColorChanged(this, EventArgs.Empty); } } } /// /// Gets or sets the border color for the control. /// /// /// Type: /// A Color that represents the border color of the control. /// public Color BorderColor { get { return this.m_borderColor; } set { if (this.m_borderColor != value) { this.m_borderColor = value; OnBorderColorChanged(this, EventArgs.Empty); } } } /// /// Gets or sets the background color for the control. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public new Color BackColor { get { return base.BackColor; } set { base.BackColor = value; } } /// /// Gets or sets the maximum value of the range of the control. /// /// /// Type: /// The maximum value of the range. The default is 100. /// [Browsable(true)] [Description("The upper bound of range this ProgressBar is working with.")] public int Maximum { get { return this.m_iMaximum; } set { if (this.m_iMaximum != value) { if (value < 0) { object[] args = new object[] { "Maximum", value.ToString(CultureInfo.CurrentCulture), "Maximum" }; throw new ArgumentOutOfRangeException("Maximum", string.Format(CultureInfo.InvariantCulture, Resources.IDS_InvalidLowBoundArgument, args)); } if (this.m_iMinimum > value) { this.m_iMinimum = value; } this.m_iMaximum = value; if (this.m_iValue > this.m_iMaximum) { this.m_iValue = this.m_iMaximum; } UpdatePos(); } } } /// /// Gets or sets the minimum value of the range of the control. /// /// /// Type: /// The minimum value of the range. The default is 0. /// [Browsable(true)] [Description("The lower bound of range this ProgressBar is working with.")] public int Minimum { get { return this.m_iMinimum; } set { if (this.m_iMinimum != value) { if (value < 0) { object[] args = new object[] { "Minimum", value.ToString(CultureInfo.CurrentCulture), "Minimum" }; throw new ArgumentOutOfRangeException("Minimum", string.Format(CultureInfo.InvariantCulture, Resources.IDS_InvalidLowBoundArgument, args)); } if (this.m_iMaximum < value) { this.m_iMaximum = value; } this.m_iMinimum = value; if (this.m_iValue < this.m_iMinimum) { this.m_iValue = this.m_iMinimum; } UpdatePos(); } } } /// /// Gets or sets the current position of the progress bar. /// /// /// Type: /// The position within the range of the progress bar. The default is 0. /// [Browsable(true)] [Description("The current value for the ProgressBar, in the range specified by the minimum and maximum properties.")] public int Value { get { return this.m_iValue; } set { if (this.m_iValue != value) { if ((value < this.m_iMinimum) || (value > this.m_iMaximum)) { throw new ArgumentOutOfRangeException("Value", string.Format(CultureInfo.InvariantCulture, Resources.IDS_InvalidBoundArgument, new object[] { "Value", value.ToString(CultureInfo.CurrentCulture), "'minimum'", "'maximum'" })); } this.m_iValue = value; UpdatePos(); } } } #endregion #region MethodsPublic /// /// Initializes a new instance of the ProgressBar class. /// public ProgressBar() { this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.ResizeRedraw, true); this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); InitializeComponent(); this.m_iMaximum = 100; this.m_backgroundColor = Color.FromArgb(20, 20, 255); this.m_valueColor = Color.FromArgb(255, 0, 255); this.m_borderColor = SystemColors.ActiveBorder; this.BackColor = Color.Transparent; } #endregion #region MethodsProtected /// /// Raises the Paint event. /// /// A PaintEventArgs that contains the event data. protected override void OnPaint(PaintEventArgs e) { using (UseAntiAlias antiAlias = new UseAntiAlias(e.Graphics)) { Graphics graphics = e.Graphics; DrawProgressBar( graphics, this.ClientRectangle, this.m_backgroundColor, this.m_valueColor, this.m_borderColor, this.RightToLeft, this.Minimum, this.Maximum, this.Value); if (string.IsNullOrEmpty(this.Text) == false) { using (UseClearTypeGridFit useClearTypeGridFit = new UseClearTypeGridFit(graphics)) { using (SolidBrush textBrush = new SolidBrush(this.ForeColor)) { using (StringFormat stringFormat = new StringFormat()) { stringFormat.FormatFlags = StringFormatFlags.NoWrap; if (this.RightToLeft == RightToLeft.Yes) { stringFormat.FormatFlags |= StringFormatFlags.DirectionRightToLeft; } stringFormat.Trimming = StringTrimming.EllipsisCharacter; stringFormat.LineAlignment = StringAlignment.Center; stringFormat.Alignment = StringAlignment.Center; Rectangle stringRectangle = this.ClientRectangle; graphics.DrawString(this.Text, this.Font, textBrush, stringRectangle, stringFormat); } } } } } } /// /// Raises the BorderColor changed event. /// /// The source of the event. /// A EventArgs that contains the event data. protected virtual void OnBorderColorChanged(object sender, EventArgs e) { this.Invalidate(true); if (this.BorderColorChanged != null) { this.BorderColorChanged(sender, e); } } /// /// Raises the BackgroundColor changed event. /// /// The source of the event. /// A EventArgs that contains the event data. protected virtual void OnBackgroundColorChanged(object sender, EventArgs e) { Invalidate(); if (this.BackgroundColorChanged != null) { this.BackgroundColorChanged(sender, e); } } /// /// Raises the ValueColor changed event. /// /// The source of the event. /// A EventArgs that contains the event data. protected virtual void OnValueColorChanged(object sender, EventArgs e) { Invalidate(true); if (this.ValueColorChanged != null) { this.ValueColorChanged(sender, e); } } #endregion #region MethodsPrivate private void UpdatePos() { this.Invalidate(true); } private static void DrawProgressBar( Graphics graphics, Rectangle clientRectangle, Color colorBackgroundEnd, Color colorValueEnd, Color borderColor, RightToLeft rightToLeft, int iMinimum, int iMaximum, int iValue) { Rectangle outerRectangle = GetRectangleBackground(clientRectangle); using (GraphicsPath outerRectangleGraphicsPath = GetBackgroundPath(outerRectangle, 4)) { if (outerRectangleGraphicsPath != null) { using (LinearGradientBrush gradientBrush = GetGradientBackBrush(outerRectangle, colorBackgroundEnd)) { if (gradientBrush != null) { graphics.FillPath(gradientBrush, outerRectangleGraphicsPath); } } // Draws the value rectangle if (iValue > 0) { Rectangle valueRectangle = GetRectangleValue(outerRectangle, rightToLeft, iMinimum, iMaximum, iValue); using (GraphicsPath valueGraphicsPath = GetValuePath(valueRectangle, rightToLeft, 5)) { using (LinearGradientBrush gradientBrush = GetGradientBackBrush(valueRectangle, colorValueEnd)) { if (gradientBrush != null) { graphics.FillPath(gradientBrush, valueGraphicsPath); } } } } using (Pen borderPen = new Pen(borderColor)) { graphics.DrawPath(borderPen, outerRectangleGraphicsPath); } } } } private static Rectangle GetRectangleBackground(Rectangle clientRectangle) { Rectangle rectangleBackground = clientRectangle; rectangleBackground.Inflate(-1, -1); return rectangleBackground; } private static Rectangle GetRectangleValue(Rectangle backgroundRectangle, RightToLeft rightToLeft, int iMinimum, int iMaximum, int iValue) { Rectangle valueRectangle = backgroundRectangle; int iProgressRange = iMaximum - iMinimum; int iValueRange = iValue - iMinimum; int iRange = (int)((float)iValueRange / (float)iProgressRange * backgroundRectangle.Width); valueRectangle.Width = iRange; if (rightToLeft == RightToLeft.Yes) { valueRectangle.X = backgroundRectangle.Width - valueRectangle.Width; } return valueRectangle; } private static GraphicsPath GetBackgroundPath(Rectangle bounds, int radius) { int x = bounds.X; int y = bounds.Y; int width = bounds.Width; int height = bounds.Height; GraphicsPath graphicsPath = new GraphicsPath(); graphicsPath.AddArc(x, y, radius, radius, 180, 90); //Upper left corner graphicsPath.AddArc(x + width - radius, y, radius, radius, 270, 90); //Upper right corner graphicsPath.AddArc(x + width - radius, y + height - radius, radius, radius, 0, 90);//Lower right corner graphicsPath.AddArc(x, y + height - radius, radius, radius, 90, 90); //Lower left corner graphicsPath.CloseFigure(); return graphicsPath; } private static GraphicsPath GetValuePath(Rectangle bounds, RightToLeft rightToLeft, int radius) { int x = bounds.X; int y = bounds.Y; int width = bounds.Width; int height = bounds.Height; GraphicsPath graphicsPath = new GraphicsPath(); if (rightToLeft == RightToLeft.No) { graphicsPath.AddArc(x, y, radius, radius, 180, 90); //Upper left corner graphicsPath.AddLine(x + radius, y, x + width, y); //Upper line graphicsPath.AddLine(x + width, y, x + width, y + height); //Right line graphicsPath.AddArc(x, y + height - radius, radius, radius, 90, 90); //Lower left corner } else { graphicsPath.AddLine(x, y, width - radius, y); //Upper Line graphicsPath.AddArc(x + width - radius, y, radius, radius, 270, 90); // Upper right corner graphicsPath.AddLine(x + width, y + radius, x + width, y + radius + height - (2 * radius)); // right line graphicsPath.AddArc(x + width - radius, y + radius + height - (2 * radius), radius, radius, 360, 90); // Lower right corner graphicsPath.AddLine(x + width - radius, y + height, x, y + height); // Lower line } graphicsPath.CloseFigure(); return graphicsPath; } private static LinearGradientBrush GetGradientBackBrush(Rectangle bounds, Color backColor) { if (IsZeroWidthOrHeight(bounds)) { return null; } LinearGradientBrush linearGradientBrush = linearGradientBrush = new LinearGradientBrush(bounds, Color.White, backColor, LinearGradientMode.Vertical); if (linearGradientBrush != null) { Blend blend = new Blend(); blend.Positions = new float[] { 0.0F, 0.2F, 0.3F, 0.5F, 0.6F, 0.8F, 1.0F }; blend.Factors = new float[] { 0.3F, 0.4F, 0.5F, 0.8F, 1.0F, 1.0F, 0.9F }; linearGradientBrush.Blend = blend; } return linearGradientBrush; } /// /// Checks if the rectangle width or height is equal to 0. /// /// the rectangle to check /// true if the with or height of the rectangle is 0 else false private static bool IsZeroWidthOrHeight(Rectangle rectangle) { if (rectangle.Width != 0) { return (rectangle.Height == 0); } return true; } #endregion } }