Formulaires ne répondant pas aux événements KeyDown

Je travaille depuis un certain temps sur mon projet Windows Forms et j’ai décidé d’expérimenter les raccourcis clavier. Après un peu de lecture, j’ai pensé que je devais écrire un gestionnaire d’événement et le lier à l’événement KeyDown du formulaire:

private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.Control && e.Alt && e.KeyCode == Keys.O) { MessageBox.Show("Ctrl+Alt+O: magic!"); } } 

Je l’ai fait comme le bon moyen d’ouvrir le panneau Propriétés du concepteur Visual Studio, puis de double-cliquer sur l’événement KeyDown de mon formulaire pour générer le Form1_KeyDown événements Form1_KeyDown . Mais en testant mon application, le formulaire ne répond pas du tout au raccourci clavier Ctrl + Alt + O. Le concepteur Visual Studio a généré le code pour lier le gestionnaire d’événements au formulaire si:

 private void InitializeComponent() { // ... this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown); // ... } 

J’ai donc essayé d’append un appel à Console.WriteLine() au gestionnaire pour vérifier qu’il était appelé, mais pas de chance non plus.

En outre, j’ai essayé de définir un point d’arrêt sur l’appel de liaison d’événement (montré ci-dessus) et j’ai constaté que le programme atteignait ce point d’arrêt très bien. Mais tous les points d’arrêt que j’ai définis dans la définition même de la méthode ne sont jamais atteints.

Pour m’assurer que je faisais correctement les premières étapes, j’ai essayé de les répéter avec:

  • Une nouvelle forme dans la même solution.
    Même problème: le formulaire ne répond pas lorsque j’appuie sur le raccourci clavier Ctrl + Alt + O et que le débogueur n’entre pas dans le gestionnaire d’événements. J’ai essayé à nouveau et ça marche.

  • Une nouvelle solution WinForms.
    Cela fonctionne parfaitement: la boîte de dialog de message apparaît (l’appel de Console.WriteLine() fonctionne également).

Donc je suis assez perdu ici. Qu’est-ce qui empêche tous les formulaires de ce projet de recevoir des événements KeyDown?

Votre formulaire possède-t-il la propriété KeyPreview définie sur true?

Propriété Form.KeyPreview

Obtient ou définit une valeur indiquant si le formulaire recevra des événements clés avant que l’événement ne soit transmis au contrôle qui a le focus.

http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx

Le conseil le plus courant pour ce problème sur StackOverflow et MSDN 1 , 2 (y compris la réponse acceptée ici) est simple et rapide:

KeyDown événements KeyDown sont déclenchés sur un Form tant que sa propriété KeyPreview est définie sur true

C’est suffisant pour la plupart des objectives, mais c’est risqué pour deux raisons:

  1. KeyDown gestionnaires KeyDown ne voient pas toutes les clés . Plus précisément, “vous ne pouvez pas voir le type de frappe utilisé pour la navigation. Comme les touches de curseur et Tab, Echap et Entrée pour une boîte de dialog.”

  2. Il existe différentes manières d’intercepter les événements clés, et ils se produisent tous en séquence. KeyDown est traité en dernier . Par conséquent, KeyPreview n’est pas vraiment un aperçu, et l’événement pourrait être réduit au silence à quelques arrêts.

(Crédit à @HansPassant pour ces points.)

Au lieu de cela, remplacez ProcessCmdKey dans votre Form :

 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (keyData == Keys.Up) { // Handle key at form level. // Do not send event to focused control by returning true. return true; } return base.ProcessCmdKey(ref msg, keyData); } 

De cette façon, toutes les clés sont visibles pour la méthode et la méthode est la première en ligne pour voir l’événement.

Notez que vous avez toujours le contrôle sur le fait que les contrôles focalisés voient ou non l’événement KeyDown . Il suffit de retourner true pour bloquer l’événement KeyDown , plutôt que de définir KeyPressEventArgs.Handled sur true comme vous le feriez dans un gestionnaire d’événements KeyDown . Voici un article avec plus de détails.

Essayez de définir la propriété KeyPreview sur votre formulaire sur true. Cela a fonctionné pour moi pour enregistrer des presses à clé.