web-dev-qa-db-fra.com

Comment détecter la touche actuellement enfoncée?

Dans Windows Forms , vous pouvez connaître à tout moment la position actuelle du curseur grâce à la classe Cursors .

La même chose ne semble pas être disponible pour le clavier. Est-il possible de savoir si, par exemple, le Shift la touche est enfoncée?

Est-il absolument nécessaire de rechercher chaque notification de clavier (événements KeyDown et KeyUp)?

121
NorthWind
if ((Control.ModifierKeys & Keys.Shift) != 0) 

Ce sera également vrai si Ctrl+Shift est éteint. Si vous voulez vérifier si Shift seul est pressé,

if (Control.ModifierKeys == Keys.Shift)

Si vous êtes dans une classe qui hérite de Control (comme un formulaire), vous pouvez supprimer le Control.

160
SLaks

Le code ci-dessous indique comment détecter presque toutes les touches actuellement enfoncées, pas seulement la Shift clé.

private KeyMessageFilter m_filter = new KeyMessageFilter();

private void Form1_Load(object sender, EventArgs e)
{
    Application.AddMessageFilter(m_filter);
}


public class KeyMessageFilter : IMessageFilter
{
    private const int WM_KEYDOWN = 0x0100;
    private const int WM_KEYUP = 0x0101;
    private bool m_keyPressed = false;

    private Dictionary<Keys, bool> m_keyTable = new Dictionary<Keys, bool>();

    public Dictionary<Keys, bool> KeyTable
    {
        get { return m_keyTable; }
        private set { m_keyTable = value; }
    }

    public bool IsKeyPressed()
    {
        return m_keyPressed;
    }

    public bool IsKeyPressed(Keys k)
    {
        bool pressed = false;

        if (KeyTable.TryGetValue(k, out pressed))
        {
            return pressed;
        }

        return false;
    }

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            KeyTable[(Keys)m.WParam] = true;

            m_keyPressed = true;
        }

        if (m.Msg == WM_KEYUP)
        {
            KeyTable[(Keys)m.WParam] = false;

            m_keyPressed = false;
        }

        return false;
    }
}
55
Ash

Vous pouvez également consulter les éléments suivants si vous référencez System.Windows.Input.

if (Keyboard.Modifiers == ModifierKeys.Shift)

L'espace de noms de clavier peut également être utilisé pour vérifier l'état enfoncé d'autres touches avec Keyboard.IsKeyDown (Key) ou, si vous vous abonnez à un événement KeyDownEvent ou similaire, les arguments d'événement contiennent une liste des touches actuellement enfoncées.

23
Jeff Wain

La plupart de ces réponses sont beaucoup trop compliquées ou ne semblent pas fonctionner pour moi (par exemple, System.Windows.Input ne semble pas exister). Puis j'ai trouvé un exemple de code qui fonctionne très bien: http://www.switchonthecode.com/tutorials/winforms-accessing-mouse-and-keyboard-state

Au cas où la page disparaîtrait à l'avenir, je publie le code source correspondant ci-dessous:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace MouseKeyboardStateTest
{
  public abstract class Keyboard
  {
    [Flags]
    private enum KeyStates
    {
      None = 0,
      Down = 1,
      Toggled = 2
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern short GetKeyState(int keyCode);

    private static KeyStates GetKeyState(Keys key)
    {
      KeyStates state = KeyStates.None;

      short retVal = GetKeyState((int)key);

      //If the high-order bit is 1, the key is down
      //otherwise, it is up.
      if ((retVal & 0x8000) == 0x8000)
        state |= KeyStates.Down;

      //If the low-order bit is 1, the key is toggled.
      if ((retVal & 1) == 1)
        state |= KeyStates.Toggled;

      return state;
    }

    public static bool IsKeyDown(Keys key)
    { 
      return KeyStates.Down == (GetKeyState(key) & KeyStates.Down);
    }

    public static bool IsKeyToggled(Keys key)
    { 
      return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled);
    }
  }
}
17
parsley72

Depuis .NET Framework version 3.0, il est possible d'utiliser la méthode Keyboard.IsKeyDown à partir du nouvel espace de noms System.Windows.Input. Par exemple:

if (((Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) && Keyboard.IsKeyDown(Key.F))
{
    // CTRL + F is currently pressed
}

Bien que cela fasse partie de WPF, cette méthode fonctionne correctement pour les applications WinForm (à condition que vous ajoutiez des références à PresentationCore.dll et WindowsBase.dll). Malheureusement, cependant, les versions 3.0 et 3.5 de la méthode Keyboard.IsKeyDown ne fonctionnaient pas pour les applications WinForm. Par conséquent, si vous souhaitez l'utiliser dans une application WinForm, vous devez cibler .NET Framework 4.0 ou version ultérieure pour que cela fonctionne.

10
Steven Doggart

Vous pouvez P/Invoke descendre sur le Win32 GetAsyncKeyState pour tester n'importe quelle touche du clavier.

Vous pouvez transmettre des valeurs de l'énumération Keys (par exemple, Keys.Shift) à cette fonction. Il suffit donc de quelques lignes de code pour l'ajouter.

8
Jason Williams
if ((ModifierKeys == Keys.Control) && ((e.KeyChar & (char)Keys.F) != 0))
{
     // CTRL+F pressed !
}
5
Mahdi

Le meilleur moyen que j'ai trouvé de gérer l'entrée au clavier sur un formulaire Windows Forms est de le traiter après la frappe et avant que le contrôle ciblé reçoive l'événement. Microsoft maintient une propriété intégrée Form- nommée . KeyPreview pour faciliter cette tâche précise:

public frmForm()
{
    // ...
    frmForm.KeyPreview = true;
    // ...
}

Ensuite, les événements _KeyDown, _KeyPress et/ou _KeyUp du formulaire peuvent être marshalés pour accéder aux événements d'entrée avant que le contrôle de formulaire ciblé ne les voie, et vous pouvez appliquer une logique de gestionnaire pour capturer l'événement ou lui permettre de passer au contrôle de formulaire ciblé. .

Bien que sa structure ne soit pas aussi gracieuse que l’architecture de routage d’événements XAML , elle simplifie considérablement la gestion des fonctions au niveau du formulaire dans Winforms. Voir le Notes MSDN sur KeyPreview pour les mises en garde.

3
Hardryv
if (Form.ModifierKeys == Keys.Shift)

fonctionne pour une zone de texte si le code ci-dessus est dans l'événement keydown du formulaire et qu'aucun autre contrôle ne capture l'événement keydown pour la touche enfoncée.

Vous pouvez également souhaiter arrêter le traitement des clés avec:

e.Handled = true;
2
g.g
if (Control.ModifierKeys == Keys.Shift)
    //Shift is pressed

La position du curseur x/y est une propriété et une frappe (comme un clic de souris/déplacer de la souris) est un événement. La meilleure pratique consiste généralement à laisser l'interface être pilotée par les événements. Si vous essayez de faire un décalage + clic de souris, la seule chose dont vous auriez besoin est la suivante.

2
Rob Elliott

Dans WinForms:

if( Form.ModifierKeys == Keys.Shift )

Cela ressemble à une copie de la question de débordement de pile vous appuyez sur la touche Détecter Maj sans utiliser les événements dans Windows Forms?.

0
Will Eddins