Enabledがfalse中のクリックイベントがtrue後に実行されてしまいます。 への返答
投稿で使用できる特殊コードの説明。(別タブで開きます。)
以下の返答は逆順(新しい順)に並んでいます。
投稿者 よっしー26  (社会人)
投稿日時
2016/12/12 23:32:19
フォーム上に何個かのボタンが配置してあり、ボタンを押すと、それぞれのボタンに
対応したエクセルファイルを印刷するプログラムを作っています。
印刷処理に時間がかかるので、ボタンがクリックされるとプリンタにデータが
送られるまでの間、フォームのEnabledをfalseにして、ボタンが押されないよう
にしています。
しかし、false中にボタンがクリックされると、フォームがtrueに戻った後に、
ボタンのクリックイベントが発生してしまい、印刷がされてしまいます。
どうして、このようなことが起きてしまうのかわかりません。
false中にクリックされても、true後にイベントが発生しないようにするには
どうしたらよいのでしょうか?
ご存知の方がいらっしゃいましたら、お教えください。
対応したエクセルファイルを印刷するプログラムを作っています。
印刷処理に時間がかかるので、ボタンがクリックされるとプリンタにデータが
送られるまでの間、フォームのEnabledをfalseにして、ボタンが押されないよう
にしています。
しかし、false中にボタンがクリックされると、フォームがtrueに戻った後に、
ボタンのクリックイベントが発生してしまい、印刷がされてしまいます。
どうして、このようなことが起きてしまうのかわかりません。
false中にクリックされても、true後にイベントが発生しないようにするには
どうしたらよいのでしょうか?
ご存知の方がいらっしゃいましたら、お教えください。
「ウィンドウ メッセージ」という、一種のイベント通知として扱われます。
そしてこれらのメッセージが処理されるのは、そのアプリケーションが
ほかの作業をしていないとき、いわゆる「アイドル時」に限られます。
何か処理を行っている最中に来たメッセージは、アイドル状態になるまで
待ち行列にキューイングされ、処理可能になった時点で一気に処理されます。
Enabled = False の状態であれば、クリック操作は破棄されるはずなのでですが、
アイドル時でなければメッセージは処理されません。Click イベントという
作業をしている最中ゆえ、その破棄処理さえも待ち状態になっているわけです。
Button1_Click を抜けてアイドル時になった瞬間には破棄可能に戻りますが、
その時点では、Enabled = True に戻されているわけですから、
結果的に、クリック処理がそのまま走ってしまう、ということです。
対処方法としては、Application の Idle イベントを使うと良いでしょう。
上記では、長い処理を実施する前に、isEventProcessing 変数を True にしています。
そして、isEventProcessing フラグが True の間は、Click イベントが来ても
なにも処理しないように If 文で無視させることで、イベントの再入を防ぐようにします。
処理が終わり、アプリケーションがアイドル状態になると
Application の Idle イベント が発生しますので、そこで
isEventProcessing を False に戻してやります。
なおサンプルでは、Button1_Click 内でマウスカーソルを変更していますが
これは必須ではありません。
もちろん、Button1_Click 内で Button1.Enabled を操作するのも自由です。