Attivazione di eventi di ingresso ed uscita all'interno di un gestore di eventi
Salve a tutti!
Ho un modulo in cui devo aggiungere e rimuovere alcuni TextBox
e Label
controlli dinamicamente.
Ognuno di questi controlli da aggiungere avrà anche 3 eventi: alcune convalide in caso di a KeyPress
e altre cose su Enter
e Exit
. Il problema sono gli eventi Enter
e Exit
sembra non funzionare all'interno del modulo di classe del gestore di eventi.
Lo stesso progetto ha altri moduli di gestione degli eventi e funzionano bene (ma non hanno eventi Enter
né Exit
).
Il codice nel modulo di classe del gestore eventi è il seguente. Non inserirò il codice nel modulo del modulo perché funziona bene, è solo qualcosa su Enter
ed Exit
eventi all'interno dei gestori di eventi.
Conosci un modo per attivare azioni Enter
ed Exit
eventi di un aggiunto dinamicamente TextBox
?
EDIT: Il mio obiettivo è produrre alcune fantastiche animazioni di transizione quando TextBox
si concentra e quando perde la concentrazione. Questa animazione si verifica già con i controlli preesistenti; è una funzione che si attiva sugli eventi Enter e Exit (GotFocus e LostFocus sarebbero carini, ma non sono disponibili).
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
Risposte
Purtroppo l'elenco degli eventi esposti dal metodo Event Handler Class non include Enter
o Exit
eventi. Puoi vedere quali eventi sono disponibili nell'IDE

Senza saperne di più sul tuo progetto, è difficile consigliare alternative.
Ok, forse è un po 'spinoso, ma rispondo alla mia domanda per documentare la mia inversione di tendenza su questo problema.
Le risposte degli altri colleghi hanno ignorato le mie aspettative di funzionalità Enter
ed Exit
eventi nei moduli di classe del gestore di eventi, quindi ecco cosa ho fatto e sembra funzionare.
Il pensiero di base è il seguente: sto cercando di attivare funzioni che rendono piacevoli animazioni di transizione tra i controlli, quindi posso presumere che avrò solo bisogno di usarle: (a) Quando l'utente passa manualmente da un controllo a un altro (se il il codice riempie tutto automaticamente, non userò l'animazione, metto solo il markup finale tramite codice specifico); e (b) quando questi controlli di input sono selezionabili ( vale a dire , have TabStop = True
).
L'utente passa manualmente da un controllo all'altro facendo clic su di essi e premendo Tab
o Shift + Tab
. Sono in grado di tenere traccia di questi eventi nei moduli di classe del gestore eventi, tramite KeyUp
(ha funzionato meglio di KeyDown
me), MouseDown
(non è stato necessario provare MouseUp
) e Click
(nei controlli del pulsante di comando).
Il mio modulo ha 12 controlli statici con TabStop (5 caselle di testo, 5 caselle combinate e 2 pulsanti di comando), e potrebbe essere creato più 5 dinamicamente (3 caselle di testo e 2 caselle combinate).
Così ho creato 3 moduli di classe per i gestori di eventi (per pulsanti di comando, caselle combinate e caselle di testo) per tenere traccia degli eventi pseudo-Invio e pseudo-Uscita. In effetti, questi gestori di eventi ascoltano quando l'utente fa clic su un controllo o preme TAB o MAIUSC + TAB (dopotutto, questi sono i modi per passare manualmente a un altro controllo). Per sapere se l'utente è andato a un altro controllo o se ha fatto clic sullo stesso in cui si trovava già, ho definito 2 variabili oggetto globali chiamate oActiveControl
e oPreviousControl
, che funge da token. Se il controllo su cui si è fatto clic / scheda è diverso da oActiveControl
, significa che l'utente ha modificato i controlli, quindi devo aggiornare i miei token.
Ha funzionato molto bene (per queste misere 4 ore; non è stato testato duramente). Ecco il codice:
''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''' 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
Per salvare righe di codice, ho adattato la maestosa risposta di Gary McGill a questa domanda: VBA: Using WithEvents on UserForms
Grazie, Chris Nielsen e Variatus! Le tue spiegazioni mi hanno aiutato molto! Se qualcuno ha una risposta più chiara a questo problema, pubblicala qui. EDIT: Grazie ancora, Chris, per aver notato il problema che non riuscivo a vedere confrontando gli oggetti!