首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

自訂進度條狀態列控制項:ProgressStatusBar 完整原始碼解析與應用

     編輯:關於C語言

前言:為什麼需要自訂進度條狀態列?

標準的 StatusBar 控制項僅能顯示文字資訊,若要在狀態列面板中直接繪製進度條(如檔案下載、資料處理進度),必須繼承並重寫繪製邏輯。本文提供的 ProgressStatusBar 類別完整實現了這一需求,支援自訂最小/最大值、目前值與前景色,且透過 OwnerDraw 模式自行繪製進度區塊,效能優異且易於整合。

核心類別架構

  • ProgressStatusBar:繼承 System.Windows.Forms.StatusBar,負責管理面板集合與重寫 OnDrawItem 繪製邏輯。
  • ProgressPanel:繼承 StatusBarPanel,擴充 Minimum、Maximum、Value、ForeColor 屬性,並將 Style 設為 OwnerDraw。

完整原始碼(C#)

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; }
}

關鍵實作細節解析

1. OwnerDraw 模式與繪製邏輯

ProgressPanel 建構子將 Style 設為 StatusBarPanelStyle.OwnerDraw,告訴框架「此面板由開發者自行繪製」。ProgressStatusBar.OnDrawItem 中判斷面板型別,若為 ProgressPanel 則根據 Value / Maximum 比例計算填充寬度,使用 Graphics.FillRectangle 繪製實心進度條。

2. 型別檢查的改進建議

原始碼使用 e.Panel.GetType().ToString().EndsWith("ProgressPanel") 判斷型別,建議改為更安全的 e.Panel is ProgressPanel 或 e.Panel.GetType() == typeof(ProgressPanel),避免命名空間變更導致誤判。

3. 繪製資源釋放

範例中使用 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,適合並行任務監控。
  • 繼承 ToolStripStatusLabel:若專案已遷移至 StatusStrip(.NET 2.0+),可參考相同邏輯實作 ToolStripProgressBar 的自訂版本。

總結

ProgressStatusBar 與 ProgressPanel 僅用百行程式碼,即實現了功能完整、可高度客製化的進度條狀態列。其核心在於 OwnerDraw 機制與比例計算邏輯,理解後可輕鬆移植至 WPF、WinUI 或 Blazor 等現代框架的自訂控制項開發中。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved