Architect's Log

I'm a Cloud Architect. I'm highly motivated to reduce toils with driving DevOps.

【Windowsフォーム】ボタン二度押し対応のサンプル

Windowsフォームアプリのボタン連打対応のサンプルです。ボタンクリック処理中のボタン再押下を無効化します。詳細はソースのコメントを見てください。

以下のスレの2007年11月9日 8:55のれいさんの回答を参考に、Formクラスの拡張メソッドとして実装してみました。
VB2005 ボタン二度押し防止方法
Windows Formのボタンの二度押し防止方法ですが、別フォーラムでも同トピック、議論はあるものの 正解らしい回答を見たことがありません。変数でENABLE/DISABLEにするという案はありま ...

# ホントはApplicationクラスに実装したかったけど、静的クラスなので拡張できなかった。

ソースコード

public static class Extensions {
    /// <summary>
    /// 処理中のときはtrue。
    /// </summary>
    private static bool isProcessing = false;

    /// <summary>
    /// 処理中かどうかを検出できるようにします。
    /// </summary>
    /// <param name="self"></param>
    public static void ActivateProcessingDetection(this Form self) {
        Application.Idle += Application_Idle;

        // イベントハンドラは自動解除されないので、フォーム破棄時に解除する。
        self.Disposed += (s, e) => Application.Idle -= Application_Idle;
    }

    static void Application_Idle(object sender, EventArgs e) {
        isProcessing = false;
    }

    /// <summary>
    /// 処理を実行中かどうかを取得する。
    /// </summary>
    /// <param name="self"></param>
    /// <returns>処理を実行中のときはtrue。実行されていないときはfalse。</returns>
    public static bool IsProcessing(this Form self) {
        if (isProcessing) return true;
        isProcessing = true;
        return false;
    }
}

使い方

// 拡張メソッドの名前空間をusing しておく。

public Form1() {
    InitializeComponent();

    // 処理中かどうかを検出できるようにする。
    this.ActivateProcessingDetection();

    button1.Click += (s, e) => {
        // 処理中だったら、ボタンをクリックされても何もしない。
        if (this.IsProcessing()) return;

        button1.Enabled = false;
        // 時間のかかる処理
        Execute();
        button1.Enabled = true;
    };
}