プロが教えるわが家の防犯対策術!

VB2008です。

状態:
フォーム上にtextbox1、textbox2、button1があり、textbox1からtextbox2もしくはbutton1にフォーカスが移動したとき

1:textbox2への移動->textbox1のlostfocusイベントを通常通り発生させる。

2:button1への移動->textbox1のlostfocusイベントをキャンセルする。(1度たりとも発生させない、もしくは発生してもその処理を1度たりともさせない。)

1は通常の処理なのでなにもしなくていいと思うのですが、2の処理が上手に浮かびません。button1でフラグを立てて、textbox1_lostfocusの処理を抜けるようにしているのですが、必ず1度は処理が実行されます。

どのようにコードを書けばうまくできるでしょうか。もし、これが仕様ということなら、同じような処理をするにはどうすればよいでしょうか。

わかりにくければ補足いたします。よろしくお願いします。

A 回答 (3件)

AccessのVBAしか扱ったことのない者ですが(汗)、概念としては共通でいけると思いますので・・・



移動元のFocus喪失系のイベントが終了してからでないと、移動先のFocus取得系のイベントは
発生しないので、移動先でのフラグ処理では間に合わないと推測されます。
従って、移動先によるLostFocusイベントの切り分けは無理だと思いますので、以下はその前提での
対策になります。

1)TextBox1のLostFocusイベントでは、「TextBox1のLostFocusイベントが発生したこと」を記録する
 フラグだけを立てます(変数EveFlag=True)
2)Button1のGotFocusイベントでは、上記フラグを元に戻します(EveFlag=False)
3)TextBox1のLostFocusイベントで行いたかった処理を、イベントとは無関係のPrivate Subとして
 フォーム モジュールに記述します(WhenMoveFromTB1)
4)TextBox1・Button1以外の、Focusを取得できる全コントロールのGotFocusイベントで、上記フラグが
 オンだった場合は、上記Private SubをCallします

・・・以上が概念です。
コードの実例は以下の通り:

Option Explicit
'フォームのモジュールレベルでフラグを宣言
Dim EveFlag As Boolean

Private Sub TextBox1_LostFocus()
  'TextBox1のLostFocusイベントが発生したことをフラグに記録
  EveFlag = True
End Sub

Private Sub WhenMoveFromTB1()
  'フラグの初期化
  EveFlag = False
  'ここ(↓)には、現在、TextBox1のLostFocusイベントに記述している処理を転記
  MsgBox "LostFocusイベントの処理を代行します。"
End Sub

Private Sub TextBox2_GotFocus()
  'TextBox1のLostFocusイベントが必要なTextBox2では、代行するSubをCall
  If EveFlag = True Then Call WhenMoveFromTB1
End Sub

Private Sub Button1_GotFocus()
  'TextBox2のLostFocusイベントが無用のButton1では、フラグの初期化のみを実行
  EveFlag = False
End Sub

Private Sub TextBox3_GotFocus()
  'TextBox1のLostFocusイベントの起動が必要なコントロールがTextBox2以外にも
  'ある場合は、TextBox2と同様に、代行SubをCall
  If EveFlag = True Then Call WhenMoveFromTB1
End Sub


・・・以上です。
    • good
    • 0
この回答へのお礼

お返事ありがとうございました。
結局フラグを立てるのもめんどくさくなりtextbox2のenterイベントで処理するようにしました。

お礼日時:2008/04/27 11:41

概念としてNO.2の方で正解ですね


lostfocus→getfocus
のように進まないと、一時的にfocusが二つあることになってしまいますもんね
今回の場合、lostfocusには処理は入れられません
getfocusの時lostfocusに入れていたイベントの内容を実行させるのが、良いかと思います
もう少し突っ込むと、textbox1のlostfocusが重要なのではなく、
「textbox2がgetfocusした時、直前がtextbox1だった事」が重要と考えます

NO.2の方のように、フラグでも良いでしょうし、全てのlostfocusに抜けるコントロールの名前を変数に入れさせるようにして、変数の値が「"textbox1"」の時だけ反応するようにgetfocusのイベントの先頭にこれまでtextbox1のlostfocusに書いていた処理を実行させるのも手です
質問内容によるとbutton1のgetfocusには不要ですので、何も書かなければ、実行されません
つまり、変数の判断処理自体不要です
lostfocusするときに、変数が更新されるので、初期化は考慮しなくて済みます


関数化して Call CtrlChack(Ctrl) と呼んでみます
       ↑これを実行させる可能性のあるgetfocusの先頭に書いておく

Dim Ctrl As String 'これまでfocusがあったコントロール
↑これをFormモジュールの先頭に書いておく

Private Sub TextBox1_LostFocus()
  Ctrl = "TextBox1"
End Sub

Private Sub TextBox2_LostFocus()
  Ctrl = "TextBox2"
End Sub

Private Sub TextBox2_GotFocus()
  Call CtrlChack(Ctrl) 'こんな感じ
End Sub

Private Sub Button1_GotFocus()
 '処理不要なので特にtextbox1のlostfocusに関係する処理なし
End Sub

↓これは標準モジュールでOK(Formモジュールでも良いハズですが…)
Sub CtrlChack(Ctrl As String)
  If Ctrl = "TextBox1" Then
    'textbox1のlostfocusに書いてた処理
  End If
End Sub
    • good
    • 0
この回答へのお礼

お返事ありがとうございました。
textbox2のenterイベントで処理するようにしました。

お礼日時:2008/04/27 11:42

LeaveイベントのActiveContorolのプロパティーの項目に


button1だけでしたら、ActiveContorol.Name = "button1"などで処理を回避できます。
また、プロパティー名を忘れてしまいましたが、buttonコントロール全体を回避することもできますよ。
    • good
    • 0
この回答へのお礼

お返事ありがとうございました。
textbox2のenterイベントで処理するようにしました。

お礼日時:2008/04/27 11:40

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!