プログラマーな日々

プログラマーをやっています。好きなものは、C#, TaskChute Cloud, WorkFlowy, Backlog, AWSです。

ボタン二度押し対応のサンプル

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