Поскольку это может быть не так просто, как может выглядеть на бумаге, вот настраиваемый ProgressBar, который позволяет установить цвет полосы, а также изменить ее стиль на лету .
Свойство ProgressBarStyle
устанавливает текущий стиль: стиль BarStyle.Standard
использует метод ProgressBarRenderer.DrawHorizontalBar () для рисования своего background, в то время как BarStyle.Flat
выбирает Parent.BackColor
в качестве цвета фона и использует фиксированную белую границу для рисования границ ProgressBar и SystemColors.Highlight как цвет полосы. Конечно, его можно изменить для поддержки любого другого цвета и стандартного стиля.
Класс StringFormat используется для центрирования текста ProgressBar (только в стиле Standard
. Его также можно легко изменить), задав для горизонтального и вертикального выравнивания значение StringAlignment.Center
.
Цвет текста изменяется автоматически для адаптации к яркости цвета ProgressBar (это всего лишь простая настройка, значение HSL
само по себе не всегда может определить, какой цвет текста лучше соответствует цвету фона).
Некоторые magi c значения - это просто смещения, используемые для адаптации прямоугольников чертежа к формам, разработанным ProgressBarRenderer
Вот как это работает :
VB. Net версия Пользовательский элемент управления:
Imports System.ComponentModel
Imports System.Drawing.Drawing2D
Imports System.Drawing
Imports System.Windows.Forms
<DesignerCategory("Code")>
Public Class ProgressBarCustomColor
Inherits ProgressBar
Private m_ParentBackColor As Color = SystemColors.Window
Private m_ProgressBarStyle As BarStyle = BarStyle.Standard
Private m_FlatBorderColor As Color = Color.White
Public Sub New()
SetStyle(ControlStyles.AllPaintingInWmPaint Or
ControlStyles.UserPaint Or
ControlStyles.OptimizedDoubleBuffer, True)
End Sub
Public Enum BarStyle
Standard
Flat
End Enum
Public Property ProgressBarStyle As BarStyle
Get
Return m_ProgressBarStyle
End Get
Set
m_ProgressBarStyle = Value
If DesignMode Then Me.Parent?.Refresh()
End Set
End Property
Public Property FlatBorderColor As Color
Get
Return m_FlatBorderColor
End Get
Set
m_FlatBorderColor = Value
If DesignMode Then Me.Parent?.Refresh()
End Set
End Property
Protected Overrides Sub OnParentChanged(e As EventArgs)
MyBase.OnParentChanged(e)
m_ParentBackColor = If(Me.Parent IsNot Nothing, Me.Parent.BackColor, SystemColors.Window)
End Sub
Protected Overrides Sub OnPaintBackground(e As PaintEventArgs)
MyBase.OnPaintBackground(e)
Dim rect = Me.ClientRectangle
If m_ProgressBarStyle = BarStyle.Standard Then
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rect)
Dim baseColor = Color.FromArgb(240, Me.BackColor)
Dim highColor = Color.FromArgb(160, baseColor)
Using baseBrush = New SolidBrush(baseColor),
highBrush = New SolidBrush(highColor)
e.Graphics.FillRectangle(highBrush, 1, 2, rect.Width, 9)
e.Graphics.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1)
End Using
Else
Using pen = New Pen(m_FlatBorderColor, 2),
baseBrush = New SolidBrush(m_ParentBackColor)
e.Graphics.FillRectangle(baseBrush, 0, 0, rect.Width - 1, rect.Height - 1)
e.Graphics.DrawRectangle(pen, 1, 1, Me.ClientSize.Width - 2, Me.ClientSize.Height - 2)
End Using
End If
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim rect = New RectangleF(PointF.Empty, Me.ClientSize)
rect.Width = CType(rect.Width * (CType(Me.Value, Single) / Me.Maximum), Integer)
rect.Size = New SizeF(rect.Width - 2, rect.Height)
Dim hsl As Single = Me.ForeColor.GetBrightness()
If m_ProgressBarStyle = BarStyle.Standard Then DrawStandardBar(e.Graphics, rect, hsl)
If m_ProgressBarStyle = BarStyle.Flat Then DrawFlatBar(e.Graphics, rect, hsl)
End Sub
Private Sub DrawStandardBar(g As Graphics, rect As RectangleF, hsl As Single)
g.SmoothingMode = SmoothingMode.AntiAlias
g.CompositingQuality = CompositingQuality.HighQuality
Dim baseColor = Color.FromArgb(240, Me.ForeColor)
Dim highColor = Color.FromArgb(160, baseColor)
Using baseBrush = New SolidBrush(baseColor),
highBrush = New SolidBrush(highColor),
sf = New StringFormat(StringFormatFlags.MeasureTrailingSpaces)
sf.LineAlignment = StringAlignment.Center
sf.Alignment = StringAlignment.Center
g.FillRectangle(highBrush, 1, 2, rect.Width, 9)
g.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1)
g.DrawString($"{Me.Value} %", Me.Parent.Font,
If(hsl > 0.49F, Brushes.Black, Brushes.White), Me.ClientRectangle, sf)
End Using
End Sub
Private Sub DrawFlatBar(g As Graphics, rect As RectangleF, hsl As Single)
Using baseBrush = New SolidBrush(SystemColors.Highlight)
g.FillRectangle(baseBrush, 2, 2, rect.Width - 2, rect.Height - 4)
End Using
End Sub
End Class
C# версия:
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
[DesignerCategory("Code")]
public class ProgressBarCustomColor : ProgressBar
{
private Color m_ParentBackColor = SystemColors.Window;
private Color m_FlatBorderColor = Color.White;
private BarStyle m_ProgressBarStyle = BarStyle.Standard;
public ProgressBarCustomColor()
{
this.SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer, true);
}
public enum BarStyle { Standard, Flat }
public BarStyle ProgressBarStyle {
get => m_ProgressBarStyle;
set {
m_ProgressBarStyle = value;
if (DesignMode) this.Parent?.Refresh();
}
}
public Color FlatBorderColor {
get => m_FlatBorderColor;
set {
m_FlatBorderColor = value;
if (DesignMode) this.Parent?.Refresh();
}
}
protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
m_ParentBackColor = this.Parent?.BackColor ?? SystemColors.Window;
}
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
var rect = this.ClientRectangle;
if (m_ProgressBarStyle == BarStyle.Standard) {
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rect);
var baseColor = Color.FromArgb(240, this.BackColor);
var highColor = Color.FromArgb(160, baseColor);
using (var baseBrush = new SolidBrush(baseColor))
using (var highBrush = new SolidBrush(highColor)) {
e.Graphics.FillRectangle(highBrush, 1, 2, rect.Width, 9);
e.Graphics.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1);
}
}
else {
using (var pen = new Pen(m_FlatBorderColor, 2))
using (var baseBrush = new SolidBrush(m_ParentBackColor)) {
e.Graphics.FillRectangle(baseBrush, 0, 0, rect.Width - 1, rect.Height - 1);
e.Graphics.DrawRectangle(pen, 1, 1, this.ClientSize.Width - 2, this.ClientSize.Height - 2);
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
var rect = new RectangleF(PointF.Empty, this.ClientSize);
rect.Width = (int)(rect.Width * ((float)this.Value / this.Maximum));
rect.Size = new SizeF(rect.Width - 2, rect.Height);
float hsl = this.ForeColor.GetBrightness();
if (m_ProgressBarStyle == BarStyle.Standard) DrawStandardBar(e.Graphics, rect, hsl);
if (m_ProgressBarStyle == BarStyle.Flat) DrawFlatBar(e.Graphics, rect, hsl);
}
private void DrawStandardBar(Graphics g, RectangleF rect, float hsl)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.CompositingQuality = CompositingQuality.HighQuality;
var baseColor = Color.FromArgb(240, this.ForeColor);
var highColor = Color.FromArgb(160, baseColor);
using (var baseBrush = new SolidBrush(baseColor))
using (var highBrush = new SolidBrush(highColor))
using (var sf = new StringFormat(StringFormatFlags.MeasureTrailingSpaces)) {
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
g.FillRectangle(highBrush, 1, 2, rect.Width, 9);
g.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1);
g.DrawString($"{this.Value} %", this.Parent.Font,
hsl > .49f ? Brushes.Black : Brushes.White, this.ClientRectangle, sf);
}
}
private void DrawFlatBar(Graphics g, RectangleF rect, float hsl)
{
using (var baseBrush = new SolidBrush(SystemColors.Highlight)) {
g.FillRectangle(baseBrush, 2, 2, rect.Width - 2, rect.Height - 4);
}
}
}