2017-08-05 2 views
1

J'ai créé un formulaire dans Excel. Il se compose de 3 boutons de commande et d'un cadre contenant des cases à cocher. Les cases à cocher sont remplies dynamiquement au userform_initialize en fonction des tableaux d'une feuille Excel (l'idée étant la personnalisation facile de l'utilisateur). La raison de la trame est qu'il peut y avoir beaucoup de cases à cocher et je veux que l'utilisateur puisse les faire défiler.Impossible de définir Userform.KeyPreview sur true

Mon but est maintenant de créer des raccourcis clavier pour le formulaire. Où je suis coincé est que je ne peux pas force brute écrire KeyDown gestionnaires pour chacune des cases à cocher parce que je ne sais pas lesquels existeront. Je me rends compte que ce serait aussi mieux si je pouvais avoir le gestionnaire d'événement au niveau du formulaire. Googling m'a trouvé la propriété KeyPreview du formulaire. Malheureusement, la fenêtre de propriétés dans VBA IDE ne l'affiche pas et quand j'essaie d'y accéder par programmation en réglant Me.KeyPreview = True à userform_initialize VBA renvoie une erreur de compilation: "Méthode ou membre de données introuvable" - ce que je m'attendais à ce qu'il ne soit pas dans la fenêtre des propriétés, mais valait la peine d'essayer. J'ai l'impression qu'il y a quelque chose qui me manque, alors j'ai pensé que je demanderais avant de passer du temps à apprendre à écrire puis à réécrire le formulaire entièrement en classe comme dans le code MSDN: https://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview(v=vs.110).aspx. Suis-je chanceux? J'avoue être à la limite de mes connaissances VBA et je cherche à aller plus loin. Tous les concepts généraux ou le contexte que je devrais rouge seraient grandement appréciés.

MISE À JOUR

Je pense maintenant au sujet GetAsyncKeyState et Application.Onkey. D'après ce que je comprends, GetAsyncKeyState fonctionne seulement dans une boucle infinie DoEvents. J'ai essayé d'en initier un en espérant que le formulaire serait toujours chargé, mais bien sûr, il n'a pas - je suis coincé dans la boucle.

Le problème avec Application.Onkey est que je ne peux pas affecter la fonction d'événement à la clé dans le module userform. Cela m'intrigue parce que d'autres gestionnaires d'événements peuvent aller dans le module userform. En fait, je le mettrais dans la procédure Userform_Initialize. Est-ce parce que ce n'est pas un événement de formulaire mais un événement d'application?

EDIT

Il me semble avoir quelque chose qui fonctionne, mais pour la question étrange décrit ici: Event handling class will not fire unless I use a breakpoint when initializing form Merci @UGP

+0

Le lien est pour VB.NET et non VBA. Cela ne peut pas simplement s'appliquer à cela. KeyPreview est seulement une méthode dans Access VBA et ne fonctionne pas dans Excel. – UGP

+0

Peut-être que [this] (https://codereview.stackexchange.com/questions/44361/form-controls-single-event-handler-for-multiple-controls-without-sacrifices) peut vous aider. – UGP

+0

Merci beaucoup @UGP, j'espérais jusqu'à la toute fin. L'affiche dit "KeyPress" est un cas spécial - en activant KeyPreview au niveau du formulaire, je peux capturer le KeyAscii requis dans mlastKeyPressedAscii dans l'événement Form_KeyPress du formulaire, et le transmettre ". Il semble que je suis de retour à la case départ? Aussi, mise à jour posté ci-dessus. – PKB

Répondre

0

Voici un exemple, comment cela pourrait fonctionner, a trouvé here:

Pour mettre dans une classe nommée "KeyPreview":

Option Explicit 

Dim WithEvents u As MSForms.UserForm 
Dim WithEvents t As MSForms.TextBox 
Dim WithEvents ob As MSForms.OptionButton 
Dim WithEvents lb As MSForms.ListBox 
Dim WithEvents dp As MSComCtl2.DTPicker 

Event KeyDown(ByVal KeyCode As Integer, ByVal Shift As Integer) 
'Event KeyPress(ByVal KeyAscii As Integer) 

Private FireOnThisKeyCode As Integer 

Friend Sub AddToPreview(Parent As UserForm, KeyCode As Integer) 
Dim c As Control 
Set u = Parent 
FireOnThisKeyCode = KeyCode 
For Each c In Parent.Controls 
Select Case TypeName(c) 
Case "TextBox" 
Set t = c 
Case "OptionButton" 
Set ob = c 
Case "ListBox" 
Set lb = c 
Case "DTPicker" 
Set dp = c 
End Select 
Next c 
End Sub 

Private Sub u_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) 
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift) 
End Sub 

Private Sub t_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) 
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift) 
End Sub 

Private Sub ob_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) 
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift) 
End Sub 

Private Sub lb_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) 
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift) 
End Sub 

Private Sub dp_KeyDown(KeyCode As Integer, ByVal Shift As Integer) 
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift) 
End Sub 

à mettre dans le userform:

Option Explicit 

Dim WithEvents kp As KeyPreview 

Private Sub UserForm_Initialize() 
Set kp = New KeyPreview 
kp.AddToPreview Me, 114 
End Sub 

Private Sub kp_KeyDown(ByVal KeyCode As Integer, ByVal Shift As Integer) 
MsgBox "F3 was pressed..." 
End Sub 

Il fonctionne avec TextBoxes, OptionButtons, ListBoxes et DTPickers. Les autres contrôles susceptibles d'être ciblés devront également être traités.

+0

Merci beaucoup @UGP! Il peut se passer quelques jours avant que je puisse l'essayer, car le travail de 9-5 ne l'est pas aussi, mais j'apprécie votre aide! – PKB

+0

Merci encore @UGP, comme vous pouvez le voir sur https://stackoverflow.com/questions/45662687/event-handling-class-will-not-fire-unless-i-use-a-breakpoint-when-initializing- Votre approche semble fonctionner, mais j'ai rencontré un problème étrange qui, je pense, justifie son propre message. – PKB