イベントハンドラー内でのEnterイベントとExitイベントのトリガー
みなさん、あられ!
一部TextBox
とLabel
コントロールを動的に追加および削除する必要があるフォームがあります。
以下の場合は、いくつかの検証:これらのコントロールのそれぞれは、3つのイベントがあります追加するKeyPress
と、上のいくつかの他のものEnter
とはExit
。問題はイベントでEnter
ありExit
、イベントハンドラークラスモジュール内では機能しないようです。
同じプロジェクトに他のイベントハンドラモジュールがあり、それらはうまく機能します(ただし、イベントEnter
もありませんExit
)。
イベントハンドラクラスモジュールのコードは次のとおりです。それが正常に動作していますので、私はそれがちょうど約何か、フォームモジュール内のコードを投稿しないだろうEnter
し、Exit
イベントハンドラ内のイベント。
動的に追加されたアクションEnter
やExit
イベントをトリガーする方法を知っていますTextBox
か?
編集:私の目的は、TextBox
フォーカスが合ったときとフォーカスがなくなったときに、クールなトランジションアニメーションを作成することです。このアニメーションは、既存のコントロールですでに発生しています。これは、EnterイベントとExitイベントでトリガーされる関数です(GotFocusとLostFocusがあれば便利ですが、使用することもできません)。
Option Explicit
Private WithEvents moTextDate As MSForms.TextBox
Public Property Set DateTextBox(ByVal oTxtBox As MSForms.TextBox)
Set moTextDate = oTxtBox
End Property
Private Sub moTextDate_Enter()
' Things to do on receiving focus
End Sub
Private Sub moTextDate_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If ValidateNumbers(KeyAscii, "/", ":", " ") = False Then KeyAscii = 0
End Sub
Private Sub moTextDate_Exit(ByVal Cancel As MSForms.ReturnBoolean)
' Things to do when lost focus
End Sub
回答
残念ながら、Event Handler Classメソッドによって公開されるイベントのリストには、Enter
またはExit
イベントが含まれていません。IDEで利用可能なイベントを確認できます

あなたのプロジェクトについてもっと知らなければ、他の方法を勧めるのは難しいです。
わかりました、多分それはちょっと厄介です、しかし私はこの問題に関する私のターンアラウンドを文書化するために私の質問に答えています。
他の仲間の回答は、イベントハンドラークラスモジュールの機能Enter
とExit
イベントに対する私の期待を却下したので、これが私がしたことであり、うまくいくようです。
基本的な考え方は次のとおりです。コントロール間で快適な遷移アニメーションを作成する関数をトリガーしようとしているので、それらを使用するだけでよいと想定できます。(a)ユーザーが手動でコントロールから別のコントロールに移動する場合(コードはすべてを自動的に埋めます。アニメーションは使用せず、特定のコードを介して終了マークアップを配置するだけです。及び(b)は、これらの入力コントロールが選択されている場合(すなわち、有しますTabStop = True
)。
ユーザーは、コントロールをクリックしてTab
またはを押すことにより、コントロールから別のコントロールに手動で移動しますShift + Tab
。これらのイベントは、イベントハンドラークラスモジュールで、(私KeyUp
よりもうまく機能KeyDown
しました)、MouseDown
(試す必要はありませんでしたMouseUp
)、およびClick
(コマンドボタンコントロールで)を介して追跡できます。
私のフォームには、TabStopを備えた12個の静的コントロール(5個のテキストボックス、5個のコンボボックス、2個のコマンドボタン)があり、さらに5個の動的に作成される可能性があります(3個のテキストボックスと2個のコンボボックス)。
したがって、疑似Enterイベントと疑似Exitイベントを追跡するために、3つのイベントハンドラークラスモジュール(コマンドボタン、コンボボックス、テキストボックス用)を作成しました。実際、これらのイベントハンドラーは、ユーザーがコントロールをクリックするか、TabキーまたはShift + Tabキーを押すとリッスンします(結局のところ、これらは別のコントロールに手動で移動する方法です)。ユーザーが別のコントロールに移動したのか、それとも既にいるコントロールをクリックしただけなのかを知るために、トークンとして機能するoActiveControl
andという2つのグローバルオブジェクト変数を定義しましたoPreviousControl
。クリック/タブインされたコントロールがと異なる場合oActiveControl
、これはユーザーがコントロールを変更したことを意味するため、トークンを更新する必要があります。
これは本当にうまくいきました(これらのわずか4時間の間、ハードテストされていませんでした)。コードは次のとおりです。
''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''' ANY MODULE ''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Public oActiveControl As MSForms.Control, oPreviousControl As MSForms.Control
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''' USER FORM MODULE '''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Sub UserForm_Initialize()
' On loading the UserForm, we are going to create the event handlers for the static controls.
Dim oControl As MSForms.Control
Dim oEvHandlerExitText As EvHndlExitTxt
Dim oEvHandlerExitCombo As EvHndlExitCbx
Dim oEvHandlerExitButton As EvHndlExitBtn
Dim colEventHandlers as Collection
Set colEventHandlers = New Collection
' Loop to create the event handlers and store them in a collection
For Each oControl In Me.Controls
Select Case TypeName(oControl)
Case "TextBox"
If oControl.TabStop = True Then
Set oEvHandlerExitText = New EvHndlExitTxt
Set oEvHandlerExitText.TextBox = oControl
colEventHandlers.Add oEvHandlerExitText
End If
Case "ComboBox"
If oControl.TabStop = True Then
Set oEvHandlerExitCombo = New EvHndlExitCbx
Set oEvHandlerExitCombo.ComboBox = oControl
colEventHandlers.Add oEvHandlerExitCombo
End If
Case "CommandButton"
If oControl.TabStop = True Then
Set oEvHandlerExitButton = New EvHndlExitBtn
Set oEvHandlerExitButton.Button = oControl
colEventHandlers.Add oEvHandlerExitButton
End If
End Select
Next oControl
End Sub
Private Sub UserForm_AddControl(ByVal Control As MSForms.Control)
' Whenever we add a control to the UserForm, if it is a Combobox, Textbox
' or Button, we are also creating their event handlers.
Select Case TypeName(Control)
Case "TextBox"
If Control.TabStop = True Then
Dim oEvHandlerExitText As EvHndlExitTxt
Set oEvHandlerExitText = New EvHndlExitTxt
Set oEvHandlerExitText.TextBox = Control
colEventHandlers.Add oEvHandlerExitText
End If
Case "ComboBox"
If Control.TabStop = True Then
Dim oEvHandlerExitCombo As EvHndlExitCbx
Set oEvHandlerExitCombo = New EvHndlExitCbx
Set oEvHandlerExitCombo.ComboBox = Control
colEventHandlers.Add oEvHandlerExitCombo
End If
Case "CommandButton"
If Control.TabStop = True Then
Dim oEvHandlerExitButton As EvHndlExitBtn
Set oEvHandlerExitButton = New EvHndlExitBtn
Set oEvHandlerExitButton.Button = Control
colEventHandlers.Add oEvHandlerExitButton
End If
End Select
End Sub
Private Sub UserForm_Terminate()
' On unloading the form, we need to dump the global token variables
Set oActiveControl = Nothing
Set oPreviousControl = Nothing
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''' CLASS MODULE EvHndlExitBtn ''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Option Explicit
Private WithEvents moBtn As MSForms.CommandButton
Public Property Set Button(ByVal oBtn As MSForms.CommandButton)
Set moBtn = oBtn
End Property
' The command buttons have no transitions, so there are no functions in pseudo-Enter nor
' pseudo-Exit events. This class module is here only to detect clicks or tabs which leaves
' other controls.
Private Sub moBtn_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Or KeyCode = 16 Then ' 9 = Tab, 16 = Shift + Tab
If oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
Set oActiveControl = moBtn
End If
End Sub
Private Sub moBtn_Click()
If oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
Set oActiveControl = moBtn
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''' CLASS MODULE EvHndlExitTxt ''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Option Explicit
Private WithEvents moTxtBox As MSForms.TextBox
Public Property Set TextBox(ByVal oTxtBox As MSForms.TextBox)
Set moTxtBox = oTxtBox
End Property
Private Sub moTxtBox_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Or KeyCode = 16 Then ' 9 = Tab, 16 = Shift + Tab
If Not oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
Set oActiveControl = moTxtBox
If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
' Here is the pseudo-Enter event from the TextBox reached via Tab/Shift+Tab:
' Instructions... (these instructions will have to be repeated below, so
' Instructions... consider creating a function if there are many of them.)
If Not oPreviousControl Is Nothing Then
' Here is the pseudo-Exit event from the previous control:
' Instructions... (Use oPreviousControl to refer the control which lost focus.
' Instructions... Will have to be repeated below also)
End If
End If
End If
End Sub
Private Sub moTxtBox_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If Not oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
Set oActiveControl = moTxtBox
If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
' Here is the pseudo-Enter event from the TextBox reached via mouse clicking:
' Instructions... (these instructions where repeated above, so consider
' Instructions... creating a function if there are many of them.)
If Not oPreviousControl Is Nothing Then
' Here is the pseudo-Exit event from the previous control:
' Instructions... (Use oPreviousControl to refer the control which lost focus.
' Instructions... Was repeated above also)
End If
End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''' CLASS MODULE EvHndlExitCbx ''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Option Explicit
Private WithEvents moCmbBox As MSForms.ComboBox
Public Property Set ComboBox(ByVal oCmbBox As MSForms.ComboBox)
Set moCmbBox = oCmbBox
End Property
Private Sub moCmbBox_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Or KeyCode = 16 Then
If Not oActiveControl Is Nothing Then Set oPreviousControl = oActiveControl
Set oActiveControl = moCmbBox
If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
' Here is the pseudo-Enter event from the ComboBox reached via Tab/Shift+Tab:
' Instructions... (these instructions will have to be repeated 4 times, so
' Instructions... consider creating a function if there are many of them.)
If Not oPreviousControl Is Nothing Then
' Here is the pseudo-Exit event from the previous control:
' Instructions... (Use oPreviousControl to refer the control which lost focus.
' Instructions... Will have to be repeated below also)
End If
End If
End If
End Sub
Private Sub moCmbBox_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If Not oActiveControl Is Nothing Then oPreviousControl = oActiveControl
Set oActiveControl = moCmbBox
If Not oActiveControl Is oPreviousControl Then ' If user changed controls...
' Here is the pseudo-Enter event from the ComboBox reached via mouse clicking:
' Instructions... (these instructions where repeated above, so consider
' Instructions... creating a function if there are many of them.)
If Not oPreviousControl Is Nothing Then
' Here is the pseudo-Exit event from the previous control:
' Instructions... (Use oPreviousControl to refer the control which lost focus.
' Instructions... Was repeated above also)
End If
End If
End Sub
コード行を節約するために、この質問に対するGary McGillの壮大な応答を採用しました:VBA:UserFormsでのWithEventsの使用
ありがとう、クリス・ニールセンとヴァリアタス!あなたの説明は私をとても助けてくれました!誰かがこの問題に対するより良い答えを持っているなら、ここに投稿してください。編集:オブジェクトの比較で私が見ることができなかった問題に気づいてくれてありがとう、クリス!