Got? Lost?
VBがおかしいのか、使用している他人の作った関数の仕様なのか、どうも各コントロールの GotFocus, LostFocus, Validate の動きが予測と違ってこまります。
たとえば、テキストボックスで ENTER キーを押さないでフォーカスを移動した場合、内容を編集前のものに戻さなければならないという規約があります。このため、
Private Dim StoredText as String Public Sub Text1_GotFocus() ' 現在の値を保存する StoredText = Text1.Text : ' 他にもここに記述しなければならない規約が数点… End Sub Public Sub Text1_LostFocus() ' 保存していた値に戻す Text1.Text = StoredText End Sub ' 自分的には KeyPress なのだが、先人に習って KeyDown Public Sub Textt1_KeyDown(KeyCode As Integer, Shift As Integer) If Shift<>0 or KeyCode<>vbKeyReturn Then Exit Sub ' 現在のテキストの内容で更新できることとする StoredText = Text1.Text End Sub
こんなかんじのコードをテキストボックスの数だけ書いてあるわけですが、あるとき突然、すべてのテキストボックスの内容が同じになるのです。
LostFocus イベントハンドラに Debug.Print "Text1_LostFocus" などと追加してみると、プロジェクト全体で使っているとある関数を呼び出すと、すべてのコントロールの LostFocus が発生することが判明しました。その関数は設定にしたがってグループ単位でコントロールの Enable プロパティを True/False を変更するというものなのですが、どうも現在のフォーカスと Enable の変更順序あたりでおかしい状態になっているようです。
Private Dim StoredText as String Private Dim TellControl as Control Private Sub GotFocusProc( tell As Control ) StoredText = tell.Text TellControl = tell : ' その他、規約に記載された事項 End Sub Private Sub LostFocusProc( tell as Control ) if TellControl Is tell Then _ tell.Text = StoredText End Sub Public Sub Text1_GotFocus() GotFocusProc( Text1 ) End Sub Public Sub Text1_LostFocus() LostFocusProc( Text1 ) End Sub Public Sub Text2_GotFocus() GotFocusProc( Text2 ) End Sub Public Sub Text2_LostFocus() LostFocusProc( Text2 ) End Sub
こんなかんじの対策を施しましたが、GotFocus イベントなしに LostFocus イベントが発生するのは、いったいどういうことだろうか。
こういうイベント処理を書くと、Delphi のイベントの共用化や Sender がないのがとても不便に思います。配列化するとコントロールの名前がすべて同じになるので、規約違反になってしまうし。
あ、いつだったかの日記*1にあるように、規約の都合で上記のような関数名や変数名を使うことはできないのですが、日記上では好き勝手な名称にしております。
*1:id:ladybug:20031202