2016年5月16日月曜日

VBA:非同期処理を考慮したダブルクリック防止処理

GUIコンポーネントに対するユーザの操作はしばしば、こちら(開発者側)の思惑から外れることが多いです。例えばボタンなどの場合は、ワンクリックすべきところをダブルクリックしてしまったり、何度もクリックしてしまうことがあります。そのような誤操作が起きないよう工夫が開発側に求められるわけで、一般的には、
  • ボタンの無効化
が解決策として出てきます。VBAでは、クリックイベントのサブモジュールがの中でenableやlockedのプロパティをfalseにする処理を入れれば解決できます。

しかし、ボタンクリック時の処理に「非同期処理」が入ってくると厄介です。例えば、クイズゲームのプログラムで
  • ボタンをクリックした時に「ピンポーン」と音を鳴らして正誤判定をする
という処理を考えます。VBAでは、サウンド再生にはAPIを利用しますが、これは非同期処理です。つなりサウンド再生の後のコードはすぐに実行されるので、音が鳴り終わるまでは無効化しておく必要があります。そこで、waitメソッドを呼び出してコードの実行を停止すればいいのですが、その際には、
  • Doeventの呼び出しが必須
という1点だけTIPがあります。下記のコードは、クリックをしたあと3秒間はボタンを無効にするという処理を書いています。実は、Doeventを書かないと、ダブルクリックをすると、2秒後に2回目のクリックに反応してしまいます。



VBA:フォームは既に表示されているので、モーダル表示することはできませんというエラーが出た場合

Form1に配置したボタンをクリックした際に、別のフォーム(Form2)を表示するとともに、自分のフォーム(Form1)は消し、Form2に配置されたボタンを押して再度Form1を表示するという処理を考えます。
この処理を行うには、showメソッドやhideメソッドを組み合わせたらできるということは用意に想像できますが、時々、表題にあるように
  • フォームは既に表示されているので、モーダル表示することはできません
というエラーが出る時があります。これは、各メソッドの呼び出し順に注意する必要があります。結論から言えば、
  • Hideメソッドで自身(Me)を消した後に、新しいフォーム(呼び出したいフォーム)をshowする
という手順ならエラーがでることなくきちんと動きます。