90 votes

Les touches fléchées haut, bas, gauche et droite ne déclenchent pas l'événement KeyDown.

Je suis en train de construire une application où toutes les entrées de touches doivent être gérées par la fenêtre elle-même.

J'ai mis tabstop à false pour chaque contrôle qui pourrait prendre le focus sauf un panneau (mais je ne sais pas si cela a un effet).

J'ai défini KeyPreview sur true et je gère l'événement KeyDown sur ce formulaire.

Mon problème est que parfois les touches fléchées ne répondent plus :

  • L'événement keydown n'est pas déclenché lorsque je n'ai appuyé que sur une touche fléchée.

  • L'événement keydown est déclenché si j'appuie sur une touche fléchée avec le modificateur de contrôle.

Avez-vous une idée de la raison pour laquelle ma touche fléchée a soudainement cessé de déclencher l'événement ?

0 votes

Pouvez-vous afficher le code que vous avez dans votre gestionnaire d'événement KeyDown.

0 votes

Peut-être que cela vous aidera ? stackoverflow.com/questions/902767/

3 votes

Maxim, je suis presque sûr que si une fenêtre contient des contrôles enfants, les événements de touche pour les touches fléchées seront supprimés. La question à laquelle vous avez fait référence portait sur un formulaire sans contrôles. Le problème de Daniel Waltrip n'était pas vraiment le même.

89voto

regex Points 316

J'avais exactement le même problème. J'ai considéré la réponse fournie par @Snarfblam ; cependant, si vous lisez la documentation sur MSDN, la méthode ProcessCMDKey est destinée à remplacer les événements de touche pour les éléments de menu dans une application.

Je suis récemment tombé sur cet article de microsoft, qui semble assez prometteur : http://msdn.microsoft.com/en-us/library/system.Windows.forms.control.previewkeydown.aspx . Selon microsoft, la meilleure chose à faire est de définir IsInputKey=true; dans le PreviewKeyDown après avoir détecté les touches fléchées. Ce faisant, l'événement KeyDown événement.

Cela a bien fonctionné pour moi et c'était moins compliqué que de remplacer la clé ProcessCMDKey.

2 votes

Cette solution devrait être choisie, elle est beaucoup plus propre et fonctionne à merveille.

0 votes

Oui, ça marche ! La réponse est assez claire, mais je veux préciser que l'élément IsInputKey est en e classe : e.IsInputKey=true .

3 votes

(que se passe-t-il si on le fait pour toutes les touches sans détecter les flèches ?)

65voto

alpha Points 201
    protected override bool IsInputKey(Keys keyData)
    {
        switch (keyData)
        {
            case Keys.Right:
            case Keys.Left:
            case Keys.Up:
            case Keys.Down:
                return true;
            case Keys.Shift | Keys.Right:
            case Keys.Shift | Keys.Left:
            case Keys.Shift | Keys.Up:
            case Keys.Shift | Keys.Down:
                return true;
        }
        return base.IsInputKey(keyData);
    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        switch (e.KeyCode)
        {
            case Keys.Left:
            case Keys.Right:
            case Keys.Up:
            case Key.Down:
                if (e.Shift)
                {

                }
                else
                {
                }
                break;                
        }
    }

3 votes

Notez que tous les arrêts de tabulation pour les contrôles doivent être faux (j'ai été confronté à un tel problème :D).

4 votes

Il s'agit en fait d'un piratage. Vérifiez la réponse de Rodolfo Neuber pour la réponse correcte.

19voto

Marcel Points 41

J'utilise PreviewKeyDown

    private void _calendar_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e){
        switch (e.KeyCode){
            case Keys.Down:
            case Keys.Right:
                //action
                break;
            case Keys.Up:
            case Keys.Left:
                //action
                break;
        }
    }

2 votes

Cela a très bien fonctionné pour moi, pas besoin d'hériter/de surcharger.

1 votes

Cela a très bien fonctionné, merci. Il se comporte exactement comme je m'attendais à ce qu'un événement clé se comporte.

0 votes

Ceci devrait être la réponse acceptée ! !! Utilisez simplement l'événement PreviewKeyDown. Cela fonctionne sans aucune modification. On ne pourrait pas être plus propre et plus simple.

18voto

Snarfblam Points 1836

Dérivez d'une classe de contrôle et vous pouvez surcharger la méthode ProcessCmdKey. Microsoft a choisi d'omettre ces touches des événements KeyDown parce qu'elles affectent plusieurs contrôles et déplacent le focus, mais il est très difficile de faire réagir une application à ces touches d'une autre manière.

0 votes

Il semble que ProcessCmdKey soit le seul moyen de gérer le clavier de manière précise. Merci !

4 votes

Cette réponse est complètement fausse. Si je n'avais pas déjà surchargé OnKeyDown à partir d'un contrôle de base qui gérait déjà les touches fléchées (pour changer le comportement), je ne l'aurais pas su et je l'aurais implémenté de la manière la plus difficile. Voir la réponse d'alpha ci-dessous.

1 votes

Même la réponse d'Alpha n'est pas adaptée à ma situation, mais celle de Snarfblam l'est. Merci !

2voto

Maxim Zaslavsky Points 6873

Malheureusement, il est assez difficile d'accomplir cela avec les touches fléchées, en raison des restrictions des événements KeyDown. Cependant, il existe quelques moyens de contourner ce problème :

  • Comme l'a dit @Snarfblam, vous peuvent remplacer la méthode ProcessCmdKey qui conserve la capacité d'analyser les pressions sur les touches fléchées.
  • Comme la réponse acceptée à cette question XNA dispose d'une méthode intégrée appelée Keyboard.GetState() qui vous permet d'utiliser les touches fléchées. Cependant, WinForms n'en dispose pas, mais cela peut être fait par le biais d'un P/Invoke ou par utiliser une classe qui y contribue .

Je recommande d'essayer d'utiliser cette classe. C'est assez simple à faire :

var left = KeyboardInfo.GetKeyState(Keys.Left);
var right = KeyboardInfo.GetKeyState(Keys.Right);
var up = KeyboardInfo.GetKeyState(Keys.Up);
var down = KeyboardInfo.GetKeyState(Keys.Down);

if (left.IsPressed)
{
//do something...
}

//etc...

Si vous utilisez cette méthode en combinaison avec l'événement KeyDown, je pense que vous pouvez atteindre votre objectif de manière fiable.

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