How to detect the currently pressed key?

265,020

Solution 1

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

This will also be true if Ctrl+Shift is down. If you want to check whether Shift alone is pressed,

if (Control.ModifierKeys == Keys.Shift)

If you're in a class that inherits Control (such as a form), you can remove the Control.

Solution 2

The code below is how to detect almost all currently pressed keys, not just the Shift key.

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

Solution 3

You can also look at the following if you use WPF or reference System.Windows.Input

if (Keyboard.Modifiers == ModifierKeys.Shift)

The Keyboard namespace can also be used to check the pressed state of other keys with Keyboard.IsKeyDown(Key), or if you are subscribing to a KeyDownEvent or similar event, the event arguments carry a list of currently pressed keys.

Solution 4

Most of these answers are either far too complicated or don't seem to work for me (e.g. System.Windows.Input doesn't seem to exist). Then I found some sample code which works fine: http://www.switchonthecode.com/tutorials/winforms-accessing-mouse-and-keyboard-state

In case the page disappears in the future I am posting the relevant source code below:

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);
    }
  }
}

Solution 5

Since .NET Framework version 3.0, it is possible to use the Keyboard.IsKeyDown method from the new System.Windows.Input namespace. For instance:

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

Even though it's part of WPF, that method works fine for WinForm applications (provided that you add references to PresentationCore.dll and WindowsBase.dll). Unfortunately, however, the 3.0 and 3.5 versions of the Keyboard.IsKeyDown method did not work for WinForm applications. Therefore, if you do want to use it in a WinForm application, you'll need to be targeting .NET Framework 4.0 or later in order for it to work.

Share:
265,020
Peter Mortensen
Author by

Peter Mortensen

Experienced application developer. Software Engineer. M.Sc.E.E. C++ (10 years), software engineering, .NET/C#/VB.NET (12 years), usability testing, Perl, scientific computing, Python, Windows/Macintosh/Linux, Z80 assembly, CAN bus/CANopen. Contact I can be contacted through this reCAPTCHA (requires JavaScript to be allowed from google.com and possibly other(s)). Make sure to make the subject specific (I said: specific. Repeat: specific subject required). I can not stress this enough - 90% of you can not compose a specific subject, but instead use some generic subject. Use a specific subject, damn it! You still don't get it. It can't be that difficult to provide a specific subject to an email instead of a generic one. For example, including meta content like "quick question" is unhelpful. Concentrate on the actual subject. Did I say specific? I think I did. Let me repeat it just in case: use a specific subject in your email (otherwise it will no be opened at all). Selected questions, etc.: End-of-line identifier in VB.NET? How can I determine if a .NET assembly was built for x86 or x64? C++ reference - sample memmove The difference between + and &amp; for joining strings in VB.NET Some of my other accounts: Careers. [/]. Super User (SU). [/]. Other My 15 minutes of fame on Super User My 15 minutes of fame in Denmark Blog. Sample: Jump the shark. LinkedIn @PeterMortensen (Twitter) Quora GitHub Full jump page (Last updated 2021-11-25)

Updated on February 08, 2021

Comments

  • Peter Mortensen
    Peter Mortensen about 3 years

    In Windows Forms, you can know, at any time, the current position of the cursor thanks to the Cursors class.

    The same thing doesn't seem to be available for the keyboard. Is it possible to know if, for example, the Shift key is pressed?

    Is it absolutely necessary to track down every keyboard notification (KeyDown and KeyUp events)?

    • epotter
      epotter almost 15 years
      Are you working in a WPF environment or something else?
    • Will Eddins
      Will Eddins almost 15 years
      @epotter: Second word states WinForms.
  • Admin
    Admin almost 15 years
    He may not care, but I just wanted to pont it out :p
  • Maxim Alexeyev
    Maxim Alexeyev almost 15 years
    Actually Keyboard.Modifiers do not always work properly. Had to find the hard way: discoveringdotnet.alexeyev.org/2008/09/…
  • Jeff Wain
    Jeff Wain almost 15 years
    Except this is not using Forms modifiers, System.Windows.Input modifiers is a different namespace and has worked fine for us every time.
  • Ash
    Ash over 14 years
    Unless I'm missing something, you haven't answered the question properly. The OP is asking about all keys and used the Shift key as an example only. So how do you detect other keys such as A to Z, 0 to 9 etc.
  • SLaks
    SLaks over 14 years
    Given that he accepted the answer, it appears that he only needed modifier keys. If you want other keys, you'll need to call the GetKeyState API function.
  • Ash
    Ash over 14 years
    no need for GetKeyState. You just need to add a message filter. See my answer.
  • SLaks
    SLaks over 14 years
    GetKeyState would be more efficient. There's no point in tracking all of the keys when Windows does it for you already.
  • Ash
    Ash over 14 years
    @Slaks, unless you have some benchmark data, you're guessing. Moreover GetKeyState will tell you the state of a key, if you can trap that keyboard event in the first place. My reading of the question is that the OP wants to know how to get the state of a key at any time. So GetKeyState by itself is useless.
  • Einstein X. Mystery
    Einstein X. Mystery over 12 years
    Keyboard wasn't recognized by the compiler, but GetAsyncKeystate in user32 worked just fine. Thanks!
  • Diego Vieira
    Diego Vieira about 11 years
    just a note, this is for WPF only
  • Steven Doggart
    Steven Doggart about 11 years
    @DiegoVieira Actually, that's not true. The functionality was added as part of WPF, and it requires that those WPF libraries be referenced, but the Keyboard.IsKeyDown method works, even in a WinForm project.
  • Diego Vieira
    Diego Vieira about 11 years
    Indeed, you have to add PresentationCore.dll
  • Gabriel Ryan Nahmias
    Gabriel Ryan Nahmias over 10 years
    How exactly would you utilize this to show the keys being pressed?
  • Alfie
    Alfie almost 10 years
    System.Windows.Input exists; for others struggling with this you need to add a reference to PresentationCore, and an additional reference to WindowsBase to access the System.Windows.Input.Key enumeration. This info can always be found on MSDN.
  • LMK
    LMK over 9 years
    Note this doesn't work (in WinForms) if targeting .Net 3.5 or earlier, only 4.0+, due to change in implementation of Win32KeyboardDevice.GetKeyStatesFromSystem(Key) :(
  • Steven Doggart
    Steven Doggart over 9 years
    @LMK Nice catch. I tested it myself and verified what you said. I updated my answer to reflect that information. Thanks!
  • Little Endian
    Little Endian over 8 years
    This class is supposed to be static, not abstract.
  • Bill Tarbell
    Bill Tarbell almost 8 years
    For a WPF solution you can use Keyboard.Modifiers == ModifierKeys.Shift (for those that came here on a search)
  • Peter Mortensen
    Peter Mortensen about 7 years
    The link is broken (404).
  • parsley72
    parsley72 about 7 years
    "In case the page disappears in the future I am posting the relevant source code below"
  • Ash
    Ash about 7 years
    Gabriel: Create an instance of KeyMessageFilter as a field in your form. Pass it to Application.AddMessageFilter() in Form_Load. Then call IsKeyPressed() on this instance for each/any key that you are interested in.
  • tomuxmon
    tomuxmon almost 7 years
    instead of (Control.ModifierKeys & Keys.Shift) != 0 one can use Control.ModifierKeys.HasFlag(Keys.Shift)
  • SLaks
    SLaks almost 7 years
    @tomuxmon: This answer was written before HasFlag existed :)
  • BenKoshy
    BenKoshy about 6 years
    @Ash thanks for your answer - would you be able to do a code example for checking for the SHIFT key etc. above?
  • Goodies
    Goodies about 3 years
    This is a nice example class, but for my purpose this did not work. When the key is pressed during a button click, the release event will not arrive. So next time I press my button, KeyMessageFilter reports that the key is still pressed, IsKeyPressed remains true. I changed to using the Control key and the solution that was approved here, using ModifierKeys.