web-dev-qa-db-fra.com

Les flèches haut, bas, gauche et droite ne déclenchent pas l'événement KeyDown

Je construis une application où toutes les entrées clés doivent être gérées par les fenêtres elles-mêmes.

Je règle tabstop sur false pour chaque contrôle qui peut saisir 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 j'ai appuyé uniquement 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 arrête soudainement de tirer?

64
Martin Delille
    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 Keys.Down:
                if (e.Shift)
                {

                }
                else
                {
                }
                break;                
        }
    }
55
alpha

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

Je suis récemment tombé sur cet article de Microsoft, qui semble très prometteur: http://msdn.Microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx . Selon Microsoft, la meilleure chose à faire est de définir e.IsInputKey=true; dans l'événement PreviewKeyDown après la détection des touches de direction. Cela déclenchera l'événement KeyDown.

Cela fonctionnait assez bien pour moi et était moins astucieux que de remplacer ProcessCMDKey.

54
Rodolfo Neuber

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;
        }
    }
15
Marcel

Voir Réponse de Rodolfo Neuber pour la meilleure réponse


(Ma réponse originale):

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

15
snarf

J'ai eu un problème similaire lors de l'appel de la fenêtre WPF à partir de WinForms.

var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
    ElementHost.EnableModelessKeyboardInterop(wpfwindow);
    wpfwindow.Show();

Cependant, montrer la fenêtre comme un dialogue , cela a fonctionné

var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
    ElementHost.EnableModelessKeyboardInterop(wpfwindow);
    wpfwindow.ShowDialog();

J'espère que cela t'aides.

2
Janez Krnc

Malheureusement, il est assez difficile d'y parvenir avec les touches fléchées, en raison des restrictions imposées par les événements KeyDown. Cependant, il existe plusieurs façons de contourner ce problème:

  • Comme @Snarfblam l'a déclaré, vous pouvez remplacer la méthode ProcessCmdKey, qui permet d'analyser les pressions sur les touches fléchées.
  • En tant que la réponse acceptée de cette question États, XNA dispose d'une méthode intégrée appelée Keyboard.GetState (), qui vous permet d'utiliser les entrées avec les touches fléchées. Cependant, WinForms ne l’a pas, mais cela peut être fait avec un P/Invoke, ou avec en utilisant une classe qui l’aide.

Je recommande d'essayer d'utiliser cette classe. C'est assez simple de le 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 l'utilisez en combinaison avec l'événement KeyDown, je pense que vous pouvez atteindre votre objectif de manière fiable.

2
Maxim Zaslavsky
protected override bool IsInputKey(Keys keyData)
{
    if (((keyData & Keys.Up) == Keys.Up)
        || ((keyData & Keys.Down) == Keys.Down)
        || ((keyData & Keys.Left) == Keys.Left)
        || ((keyData & Keys.Right) == Keys.Right))
        return true;
    else
        return base.IsInputKey(keyData);
}
0
google dev

Pour capturer les séquences de touches dans un contrôle Forms, vous devez dériver une nouvelle classe basée sur la classe du contrôle que vous souhaitez et remplacer le ProcessCmdKey ().

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    //handle your keys here
}

Exemple :

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    //capture up arrow key
    if (keyData == Keys.Up )
    {
        MessageBox.Show("You pressed Up arrow key");
        return true;
    }

    return base.ProcessCmdKey(ref msg, keyData);
}

Source complète ... Touches fléchées en C #

Vayne

0
vaynenick

Je pense que la meilleure solution consiste à le gérer comme le dit MSDN http://msdn.Microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx

Mais manipulez-le, comme vous en avez vraiment besoin. Ma façon (dans l'exemple ci-dessous) est d'attraper chaque KeyDown ;-)

    /// <summary>
    /// onPreviewKeyDown
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
    {
        e.IsInputKey = true;
    }

    /// <summary>
    /// onKeyDown
    /// </summary>
    /// <param name="e"></param>
    protected override void OnKeyDown(KeyEventArgs e)
    {
        Input.SetFlag(e.KeyCode);
        e.Handled = true;
    }

    /// <summary>
    /// onKeyUp
    /// </summary>
    /// <param name="e"></param>
    protected override void OnKeyUp(KeyEventArgs e)
    {
        Input.RemoveFlag(e.KeyCode);
        e.Handled = true;
    }
0
Marcus Dock

j'ai eu le même problème et utilisais déjà le code dans la réponse sélectionnée. ce lien était la réponse pour moi; peut-être pour d'autres aussi.

Comment désactiver la navigation sur WinForm avec des flèches en C #?

0
4mla1fn