In Progress Dialog

The following C# code shows how to make a Progress Bar in a dialog window that can be shown for tasks that run for an undetermined amount of time.

Instead of a regular progress bar that progresses from 0 to 100%, this one shows a little indicator that scrolls back and forth, while in the background the time consuming task does its work. Once the task has completed, the dialog window with the progress bar closes automatically.

The dialog with the progress bar is contained in a class file called WaitDialog.cs, for which the source code is shown further below. Here is an example of how WaitDialog can be used:

private WaitDialog waitDialog;

// Event executed when a button is pressed.
private void btnDoStuff_Click(object sender, EventArgs e)
{
  BackgroundWorker worker = new BackgroundWorker();
  worker.DoWork += new DoWorkEventHandler(MyDoFunction);
  worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(MyCompletedFunction);

  waitDialog = new WaitDialog(worker);
  waitDialog.ShowDialog();
}

private void MyDoFunction(object sender, DoWorkEventArgs e)
{
  // Do time consuming stuff.
}

private void MyCompletedFunction(object sender, RunWorkerCompletedEventArgs e)
{
  // Time consuming stuff is done.
  waitDialog.DoneWaiting();
}

Source code for WaitDialog.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace My.Project
{
  public class WaitDialog : Form
  {
    private IContainer components = null;
    private Label label1;
    private WaitingProgressBar progressBar1;

    private Thread waitingThread;
    private BackgroundWorker worker;

    private class Anim : Control
    {
      private WaitingProgressBar pBar;
      private delegate void NextStep();
      private NextStep nextStep;
      public Anim(WaitingProgressBar progressBar)
      {
        pBar = progressBar;
        nextStep = new NextStep(nextStepMethod);
      }
      public void DoIt()
      {
        while (true)
        {
          Thread.Sleep(100);
          pBar.Invoke(nextStep);
        }
      }
      private void nextStepMethod()
      {
        pBar.NextStep();
      }
    }

    private class WaitingProgressBar : ProgressBar
    {
      private int inc = 1;
      private int indWidth = 25;
      private int stepSize = 1;
      private int barWidth = 1;

      public WaitingProgressBar()
        : base()
      {
        barWidth = ClientSize.Width * indWidth / 100;
        this.SetStyle(ControlStyles.UserPaint, true);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.DoubleBuffer, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.Paint += OnPaint;
      }

      public int IndicatorWidthPct
      {
        get { return indWidth; }
        set { indWidth = value; barWidth = ClientSize.Width * indWidth / 100; }
      }

      public int StepSize
      {
        get { return stepSize; }
        set { stepSize = value; }
      }

      public void NextStep()
      {
        if ((inc > 0 && Value >= Maximum) || (inc < 0 && Value <= Minimum))
        {
          if (inc > 0)
          {
            inc = -1;
          }
          else
          {
            inc = 1;
          }
        }
        Value += (inc * stepSize);
      }

      private void OnPaint(object sender, PaintEventArgs e)
      {
        Graphics gr = e.Graphics;
        SolidBrush foreColor = new SolidBrush(ForeColor);
        int width = e.ClipRectangle.Width;
        int bw = width * Value / Maximum;
        if (inc < 0)
        {
          int ew = bw + barWidth;
          if (ew > width) { ew = width; }
          gr.FillRectangle(foreColor, bw, e.ClipRectangle.Y, (ew-bw), e.ClipRectangle.Height);
        } else {
          int ew = bw - barWidth;
          if (ew < 0) { ew = 0; }
          gr.FillRectangle(foreColor, ew, e.ClipRectangle.Y, (bw-ew), e.ClipRectangle.Height);
        }
      }
    }

    public WaitDialog(BackgroundWorker bgWorker)
    {
      worker = bgWorker;
      InitializeComponent();
    }

    private void WaitDialog_Load(object sender, EventArgs e)
    {
      waitingThread = new Thread(new ThreadStart((new Anim(progressBar1)).DoIt));
      waitingThread.Start();
      worker.RunWorkerAsync();
    }

    public void DoneWaiting()
    {
      waitingThread.Abort();
      waitingThread.Join();
      waitingThread = null;
      Close();
    }

    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    private void InitializeComponent()
    {
      this.label1 = new Label();
      this.progressBar1 = new WaitingProgressBar();
      this.SuspendLayout();
      // 
      // label1
      // 
      this.label1.AutoSize = true;
      this.label1.Font = new Font("Microsoft Sans Serif",
        11F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(0)));
      this.label1.Location = new Point(12, 9);
      this.label1.Name = "label1";
      this.label1.Size = new Size(206, 18);
      this.label1.TabIndex = 0;
      this.label1.Text = "In Progress. Please wait...";
      // 
      // progressBar1
      // 
      this.progressBar1.Location = new Point(12, 30);
      this.progressBar1.Name = "progressBar1";
      this.progressBar1.Size = new Size(212, 23);
      this.progressBar1.Style = ProgressBarStyle.Continuous;
      this.progressBar1.StepSize = 4;
      this.progressBar1.TabIndex = 1;
      // 
      // WaitDialog
      // 
      this.AutoScaleDimensions = new SizeF(6F, 13F);
      this.AutoScaleMode = AutoScaleMode.Font;
      this.ClientSize = new Size(236, 60);
      this.ControlBox = false;
      this.Controls.Add(progressBar1);
      this.Controls.Add(label1);
      this.MaximizeBox = false;
      this.MinimizeBox = false;
      this.Name = "WaitDialog";
      this.ShowIcon = false;
      this.ShowInTaskbar = false;
      this.SizeGripStyle = SizeGripStyle.Hide;
      this.StartPosition = FormStartPosition.CenterParent;
      this.Text = "In Progress";
      this.Load += new EventHandler(WaitDialog_Load);
      this.ResumeLayout(false);
      this.PerformLayout();
    }
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *

*