進捗表示ダイアログ

見た目

メインフォーム

public partial class MainForm : Form
{
  public MainForm()
  {
    InitializeComponent();
  }

  private void btnSelectDir_Click(object sender, EventArgs e)
  {
    FolderBrowserDialog dialog = new FolderBrowserDialog();  //フォルダ選択ダイアログ
    if (dialog.ShowDialog() == DialogResult.OK)
    {
      txtPath.Text = dialog.SelectedPath;
    }
  }

  //非同期検索ボタンクリック
  private void btnSearch_Click(object sender, EventArgs e)
  {
    FileOperationProgressInfo pinfo = new FileOperationProgressInfo();
    FileSearchProcesser procer = new FileSearchProcesser();

    procer.proc(txtPath.Text, pinfo);
    ProgressDialog dialog = new ProgressDialog(pinfo);
    dialog.ShowDialog(this);

    if (pinfo.isError() == true)
    {
      MessageBox.Show(pinfo.getErrorInfo().ToString(), "エラー");
    }
  }

  //同期検索ボタンクリック
  private void btnSyncSearch_Click(object sender, EventArgs e)
  {
    FileSearchProcesser procer = new FileSearchProcesser();

    try
    {
      Cursor = Cursors.WaitCursor;
      procer.proc(txtPath.Text);
      MessageBox.Show("終了しました", "成功");
    }
    catch (Exception exc)
    {
      MessageBox.Show(exc.ToString(), "エラー");
    }
    finally
    {
      Cursor = Cursors.Arrow;
    }
  }
}

進捗情報クラス

//進捗情報基本クラス
public abstract class ProgressInfo
{
  protected int total = 0;
  protected int count = 0;
  protected bool is_error = false;
  protected bool is_cancel = false;
  protected bool is_end = false;
  protected Exception exception = null;
  protected Object target = "";

  public ProgressInfo() { }

  public int getTotal() { return total; }
  public int getCount() { return count; }
  public bool isError() { return is_error; }
  public Exception getErrorInfo() { return exception; }
  public bool isCancel() { return is_cancel; }
  public bool isEnd() { return is_end; }
  public void cancel(){ this.is_cancel = this.is_end = true; }

  public abstract String getProcType();  //処理種類取得
  public abstract String getProcTargetName(); //処理対象取得
  public abstract String getProcDetailMessage();  //処理詳細メッセージ取得
}

  //ファイル操作用ProgressInfo
  public class FileOperationProgressInfo : ProgressInfo
  {
    public enum ProcType
    {
      CREATE = 0,
      DELETE,
      COPY,
      MOVE,
      EDIT,
      SEARCH,
    }

    #region "操作名称Getter"
    private class ProcTypeNameGetter
    {
      protected int hashcode;

      public ProcTypeNameGetter() { }

      public virtual bool isTarget(int hashcode)
      {
        if (hashcode == this.hashcode)
          return true;
        else
          return false;
      }

      public virtual String getName() { return ""; }
    }

    private class DefaultGetter : ProcTypeNameGetter
    {
      public DefaultGetter() : base() { }
      public override bool isTarget(int hashcode){ return true; }
    }

    private class CreateNameGetter : ProcTypeNameGetter
    {
      public CreateNameGetter() : base() { hashcode = ProcType.CREATE.GetHashCode(); }
      public override string getName(){ return "作成"; }
    }

    private class DeleteNameGetter : ProcTypeNameGetter
    {
      public DeleteNameGetter() : base() { hashcode = ProcType.DELETE.GetHashCode(); }
      public override string getName() { return "削除"; }
    }

    private class CopyNameGetter : ProcTypeNameGetter
    {
      public CopyNameGetter() : base() { hashcode = ProcType.COPY.GetHashCode(); }
      public override string getName() { return "コピー"; }
    }

    private class MoveNameGetter : ProcTypeNameGetter
    {
      public MoveNameGetter() : base() { hashcode = ProcType.MOVE.GetHashCode(); }
      public override string getName() { return "移動"; }
    }

    private class EditNameGetter : ProcTypeNameGetter
    {
      public EditNameGetter() : base() { hashcode = ProcType.EDIT.GetHashCode(); }
      public override string getName() { return "編集"; }
    }

    private class SearchNameGetter : ProcTypeNameGetter
    {
      public SearchNameGetter() : base() { hashcode = ProcType.SEARCH.GetHashCode(); }
      public override string getName() { return "検索"; }
    }
    #endregion

    private ProcType type;
    private List<ProcTypeNameGetter> name_getters = new List<ProcTypeNameGetter>();

    public FileOperationProgressInfo() : base()
    {
      name_getters.Add(new CreateNameGetter());
      name_getters.Add(new DeleteNameGetter());
      name_getters.Add(new CopyNameGetter());
      name_getters.Add(new MoveNameGetter());
      name_getters.Add(new EditNameGetter());
      name_getters.Add(new SearchNameGetter());
      name_getters.Add(new ProcTypeNameGetter());  //最終要素には必ず一致するGetter
    }

    public void setInfo(int total, int count, String target, ProcType type, bool end)
    {
      this.total = total;
      this.count = count;
      this.type = type;
      this.is_end = end;
      this.target = target;
    }

    public override string getProcType()
    {
      for (int i = 0; i < name_getters.Count; i++)
      {
        if(name_getters[i].isTarget(type.GetHashCode()) == true)
        {
          return name_getters[i].getName();
        }
      }

      return ""; //実際には到達しない
    }

    public override string getProcTargetName()
    {
      return target.ToString();   
    }

    public override string getProcDetailMessage()
    {
      return getProcType() + "中: " + getProcTargetName();
    }

    internal void setErrorInfo(Exception exc)
    {
      this.is_error = true;
      this.is_end = true;
      this.exception = exc;
    }
  }

進捗表示ダイアログ

public partial class ProgressDialog : Form
{
  private ProgressInfo pinfo;

  public ProgressDialog(ProgressInfo pinfo)
  {
    InitializeComponent();

    this.pinfo = pinfo;
    this.timer1.Enabled = false;
  }
  
  private void ProgressDialog_Load(object sender, EventArgs e)
  {
    /*
     * ロード時にタイマーを有効にする。
     * 進捗に変化が起こるまで(Totalが増える)待機する。
     */
    this.timer1.Interval = 50;
    this.timer1.Enabled = true;

    this.Owner.Cursor = Cursors.WaitCursor;
    while (pinfo.getTotal() <= 0)
      continue;
    this.Owner.Cursor = Cursors.Arrow;
  }

  private void timer1_Tick(object sender, EventArgs e)
  {
    /*
     * 50ms周期でタイマーイベントが動作する。
     * その際にProgressInfoから情報を取得、表示する。
     * また、処理がキャンセルされた場合は処理を中断する。
     */
    if (pinfo.isEnd() | pinfo.isCancel() | pinfo.isError() == true)
    {
      Close();
    }

    this.Text = pinfo.getProcType();
    progressBar1.Minimum = 0;
    progressBar1.Maximum = pinfo.getTotal();
    progressBar1.Value = pinfo.getCount();
    lblMsg.Text = pinfo.getProcDetailMessage();
  }

  private void btnCancel_Click(object sender, EventArgs e)
  {
    pinfo.cancel();
  }
}