Ceci est un suivi à la question suivante: Can't set Userform.KeyPreview to trueclasse de traitement de l'événement ne se déclenche pas à moins que je casse l'initialisation formUtilisateur
Pour résumer: l'objectif est de construire un formulaire avec des boutons de commande et un cadre contenant cases à cocher. Les cases à cocher sont remplies dynamiquement à userform_initialize
dans le cadre afin que l'utilisateur puisse les parcourir. Mon problème était avec les raccourcis clavier. Il n'était pas possible d'écrire en force brute des gestionnaires KeyDown pour chacune des cases à cocher car je ne sais pas lesquelles existeront. Malheureusement, Excel ne prend pas en charge KeyPreview
, donc j'ai dû créer ma propre version. Merci à @UGP pour me donner des avenues prometteuses qui semblent fonctionner, mais pas tout à fait ...
D'abord, c'est mon module de classe appelé clsReasonPickKP
. Je crée une nouvelle instance pour chaque case à cocher pour écouter les KeyDown
événements:
Option Explicit
Dim WithEvents vChkBx As MSForms.CheckBox
Friend Sub initializeListener(cControl As control)
Set vChkBx = cControl
End Sub
Private Sub vChkBx_KeyDown(ByVal keyCode As MSForms.ReturnInteger, ByVal shift As Integer)
frm2.keyChooser keyCode
End Sub
La ligne frm2.keyChooser keyCode
lance un sous rapide situé dans le module de code formUtilisateur. Code ci-dessous:
Public Sub keyChooser(ByVal keyCode As MSForms.ReturnInteger)
Select Case keyCode
Case vbKeyEscape: cancelBtn_Click
Case vbKeyReturn: completeDecision_Click
Case vbKeyN: customizeNote_Click
Case vbKeyS: resetDecisionNote_Click
Case vbKeyR: chkRefGrnds_Click
End Select
End Sub
J'ai copié la partie pertinente des UserForm_Initialize
sous ci-dessous. La boucle crée les cases à cocher et un écouteur d'événement pour chacun.
Sub UserForm_Initialize()
Dim x As Long, maxWidth as Long
Dim cControl As control
Dim keyPreviewCollection As New Collection
Dim keyPreviewer As clsReasonPickKP
For x = 1 To dTbl.Rows.Count - 1
Set cControl = chkBoxFrame.Controls.Add("Forms.CheckBox.1", "chkBox" & x, True)
With cControl
.AutoSize = True
.WordWrap = False
.Left = 10
.Top = 16 * x - 12
.Caption = dTbl(x, 1).Value
If .Width > maxWidth Then maxWidth = .Width
End With
Set keyPreviewer = New clsReasonPickKP
keyPreviewer.initializeListener cControl
keyPreviewCollection.Add keyPreviewer
Next x
'Additional initialization code here
End Sub
La chose étrange est que si je casse le code quelque temps après keyPreviewCollection.Add keyPreviewer
, l'auditeur ne semble pas gérer l'événement. Par exemple, si je définis un point d'arrêt à Next x
ou pour x > 1
et puis terminer l'initialisation, puis lorsque le formulaire est terminé l'initialisation et apparaît l'appelant appelle keyChooser
et tout va bien; si je ne casse pas le code comme ça, il ne piège pas l'événement ou n'appelle pas le sous-marin, etc.
Pour dépanner, j'ai essayé de ne pas ajouter keyPreviewer
à la collection, puis l'auditeur n'a pas non plus ne fonctionne pas, peu importe si ou quand je casse. Il semble que l'ajout de l'objet à la collection, et le fait d'être en mode de rupture de code après l'avoir ajouté à la collection, font en sorte que l'écouteur piège l'événement.
Egalement intéressant, si je mets un point d'arrêt dans le module vChkBx_KeyDown
, il se casse lorsque l'événement est déclenché (en supposant une pause appropriée comme décrit ci-dessus). Après avoir ensuite exécuté le code, cependant, il cesse de gérer l'événement KeyDown
lorsqu'il est déclenché.
Dans le cas où il aide, je travaille actuellement dans Excel 2010.
Est-ce que quelqu'un a une idée de ce qui se passe? Une idée de comment résoudre cela, même avec une approche de code différente?
Merci comme toujours pour l'aide de tout le monde.
La collection contenant la classe d'événements doit être au moins une variable large de l'utilisateur, si ce n'est pour le projet entier. Traduisez: ne déclarez pas la collection à l'intérieur d'un sous-marin, elle disparaîtra après la fin du sous-marin. –
Merci @PatrickLepelletier, en regardant en arrière, je me sens même idiot! :) – PKB