109 votes

Les formulaires ne répondent pas aux événements KeyDown

J'ai travaillé depuis un moment sur mon projet Windows Forms, et j'ai décidé d'expérimenter avec des raccourcis clavier. Après un peu de lecture, j'ai réalisé que je devais simplement écrire un gestionnaire d'événements 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 : magie !");
    }
}

J'ai fait cela à la bonne vieille manière en ouvrant le panneau Propriétés du designer Visual Studio, puis en double-cliquant sur l'événement KeyDown de mon formulaire pour générer le gestionnaire d'événements Form1_KeyDown. Mais lors de mes tests d'application, le formulaire ne répond pas du tout au raccourci clavier Ctrl+Alt+O. Cependant, le designer Visual Studio a bien généré le code pour lier le gestionnaire d'événements au formulaire :

private void InitializeComponent()
{
    // ...

    this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);

    // ...
}

J'ai alors essayé d'ajouter un appel Console.WriteLine() au gestionnaire pour vérifier s'il était appelé du tout, mais sans succès non plus.

J'ai également essayé de définir un point d'arrêt sur l'appel de liaison d'événement (indiqué juste ci-dessus) et j'ai constaté que le programme atteignait ce point d'arrêt sans problème. Cependant, les points d'arrêt que j'ai définis dans la définition de la méthode ne sont jamais atteints.

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

  • Un nouveau formulaire dans la même solution.
    Même problème : le formulaire ne répond pas lorsque j'appuie sur mon raccourci clavier Ctrl+Alt+O et le débogueur ne passe même pas dans le gestionnaire d'événements. J'ai essayé à nouveau et ça marche.

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

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

219voto

STO Points 4597

Votre formulaire a-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

74voto

kdbanman Points 5711

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

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

Cela convient à la plupart des cas, mais c'est risqué pour deux raisons :

  1. Les gestionnaires KeyDown ne voient pas toutes les touches. En particulier, "vous ne pouvez pas voir le type de frappes utilisées pour la navigation. Comme les touches de curseur et Tab, Echap et Entrée pour une boîte de dialogue."

  2. Il existe plusieurs façons d'intercepter les événements de touche, et ils se produisent tous en séquence. KeyDown est géré en dernier. Par conséquent, KeyPreview n'est pas vraiment un aperçu, et l'événement pourrait être silencieux à quelques arrêts en chemin.

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

À la place, remplacez ProcessCmdKey dans votre Form :

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
    if (keyData == Keys.Up)
    {
        // Traitez la touche au niveau du formulaire.
        // Ne pas envoyer l'événement au contrôle ciblé en retournant vrai.
        return true;
    }
  return base.ProcessCmdKey(ref msg, keyData);
}

De cette façon, toutes les touches sont visibles pour la méthode, et la méthode est la première à voir l'événement.

Notez que vous avez toujours le contrôle sur le fait que les contrôles ciblés voient ou non l'événement KeyDown. Retournez simplement true pour bloquer l'événement KeyDown suivant, plutôt que de définir true comme vous le feriez dans un gestionnaire d'événement KeyDown. Ici un article avec plus de détails.

26voto

TeeBasins Points 869

Essayez de définir la propriété KeyPreview sur votre formulaire en tant que vrai. Cela a fonctionné pour moi pour enregistrer les pressions de touche.

0voto

PeakCottons Points 1

Placez ceci à l'intérieur : public [formName]() { }

this.KeyPreview = true;
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X