標準的 StatusBar 控制項僅能顯示文字資訊,若要在狀態列面板中直接繪製進度條(如檔案下載、資料處理進度),必須繼承並重寫繪製邏輯。本文提供的 ProgressStatusBar 類別完整實現了這一需求,支援自訂最小/最大值、目前值與前景色,且透過 OwnerDraw 模式自行繪製進度區塊,效能優異且易於整合。
System.Windows.Forms.StatusBar,負責管理面板集合與重寫 OnDrawItem 繪製邏輯。StatusBarPanel,擴充 Minimum、Maximum、Value、ForeColor 屬性,並將 Style 設為 OwnerDraw。using System;
using System.Drawing;
using System.Windows.Forms;
public class ProgressStatusBar : StatusBar
{
public ProgressStatusBar()
{
this.SizingGrip = false;
this.ShowPanels = true;
}
protected override void OnDrawItem(StatusBarDrawItemEventArgs e)
{
if (e.Panel.GetType().ToString().EndsWith("ProgressPanel"))
{
ProgressPanel panel = (ProgressPanel)e.Panel;
if (panel.Value > panel.Minimum)
{
int newWidth = (int)(((double)panel.Value / (double)panel.Maximum) * panel.Width);
Rectangle bounds = e.Bounds;
bounds.Width = newWidth;
using (SolidBrush brush = new SolidBrush(panel.ForeColor))
{
e.Graphics.FillRectangle(brush, bounds);
}
}
else
{
base.OnDrawItem(e);
}
}
else
{
base.OnDrawItem(e);
}
}
public void UpdateValue(ProgressPanel panel, int newValue)
{
panel.Value = newValue;
// 觸發重繪
this.Invalidate();
}
}
public class ProgressPanel : StatusBarPanel
{
private int min = 1;
private int max = 100;
private int val = 0;
private Color foreColor = Color.DarkBlue;
public ProgressPanel()
{
this.Style = StatusBarPanelStyle.OwnerDraw;
this.ForeColor = Color.DarkBlue;
}
public int Minimum { get => min; set => min = value; }
public int Maximum { get => max; set => max = value; }
public int Value { get => val; set => val = value; }
public new Color ForeColor { get => foreColor; set => foreColor = value; }
}
ProgressPanel 建構子將 Style 設為 StatusBarPanelStyle.OwnerDraw,告訴框架「此面板由開發者自行繪製」。ProgressStatusBar.OnDrawItem 中判斷面板型別,若為 ProgressPanel 則根據 Value / Maximum 比例計算填充寬度,使用 Graphics.FillRectangle 繪製實心進度條。
原始碼使用 e.Panel.GetType().ToString().EndsWith("ProgressPanel") 判斷型別,建議改為更安全的 e.Panel is ProgressPanel 或 e.Panel.GetType() == typeof(ProgressPanel),避免命名空間變更導致誤判。
範例中使用 using (SolidBrush brush = ...) 確保 IDisposable 資源及時釋放,避免 GDI 物件洩漏。
public class DemoForm : Form
{
private ProgressStatusBar statusBar;
private ProgressPanel progressPanel;
private Button btnStart;
private Timer timer;
private int current = 0;
public DemoForm()
{
// 狀態列
statusBar = new ProgressStatusBar();
progressPanel = new ProgressPanel();
progressPanel.Minimum = 0;
progressPanel.Maximum = 100;
progressPanel.Value = 0;
progressPanel.Width = 300;
progressPanel.ForeColor = Color.SteelBlue;
statusBar.Panels.Add(progressPanel);
statusBar.Dock = DockStyle.Bottom;
this.Controls.Add(statusBar);
// 開始按鈕
btnStart = new Button { Text = "開始模擬下載", Dock = DockStyle.Top };
btnStart.Click += (s, e) => { current = 0; timer.Start(); };
this.Controls.Add(btnStart);
// 計時器每 100ms 更新一次
timer = new Timer { Interval = 100 };
timer.Tick += (s, e) =>
{
if (current < 100)
{
current += 2;
statusBar.UpdateValue(progressPanel, current);
}
else timer.Stop();
};
}
[STAThread]
static void Main() { Application.Run(new DemoForm()); }
}
OnDrawItem 中使用 DrawString 於進度條中央顯示百分比文字。LinearGradientBrush 或雙緩衝繪製實現現代化視覺效果。ProgressStatusBar 可同時管理多個 ProgressPanel,適合並行任務監控。StatusStrip(.NET 2.0+),可參考相同邏輯實作 ToolStripProgressBar 的自訂版本。ProgressStatusBar 與 ProgressPanel 僅用百行程式碼,即實現了功能完整、可高度客製化的進度條狀態列。其核心在於 OwnerDraw 機制與比例計算邏輯,理解後可輕鬆移植至 WPF、WinUI 或 Blazor 等現代框架的自訂控制項開發中。