How to detect the currently pressed key?
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.
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 & 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, 2021Comments
-
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 almost 15 yearsAre you working in a WPF environment or something else?
-
Will Eddins almost 15 years@epotter: Second word states WinForms.
-
-
Admin almost 15 yearsHe may not care, but I just wanted to pont it out :p
-
Maxim Alexeyev almost 15 yearsActually Keyboard.Modifiers do not always work properly. Had to find the hard way: discoveringdotnet.alexeyev.org/2008/09/…
-
Jeff Wain almost 15 yearsExcept this is not using Forms modifiers, System.Windows.Input modifiers is a different namespace and has worked fine for us every time.
-
Ash over 14 yearsUnless 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 over 14 yearsGiven 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 over 14 yearsno need for GetKeyState. You just need to add a message filter. See my answer.
-
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 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 over 12 years
Keyboard
wasn't recognized by the compiler, butGetAsyncKeystate
in user32 worked just fine. Thanks! -
Diego Vieira about 11 yearsjust a note, this is for WPF only
-
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 about 11 yearsIndeed, you have to add PresentationCore.dll
-
Gabriel Ryan Nahmias over 10 yearsHow exactly would you utilize this to show the keys being pressed?
-
Alfie almost 10 years
System.Windows.Input
exists; for others struggling with this you need to add a reference toPresentationCore
, and an additional reference toWindowsBase
to access theSystem.Windows.Input.Key
enumeration. This info can always be found on MSDN. -
LMK over 9 yearsNote 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 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 over 8 yearsThis class is supposed to be
static
, notabstract
. -
Bill Tarbell almost 8 yearsFor a WPF solution you can use
Keyboard.Modifiers == ModifierKeys.Shift
(for those that came here on a search) -
Peter Mortensen about 7 yearsThe link is broken (404).
-
parsley72 about 7 years"In case the page disappears in the future I am posting the relevant source code below"
-
Ash about 7 yearsGabriel: 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 almost 7 yearsinstead of
(Control.ModifierKeys & Keys.Shift) != 0
one can useControl.ModifierKeys.HasFlag(Keys.Shift)
-
SLaks almost 7 years@tomuxmon: This answer was written before
HasFlag
existed :) -
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 about 3 yearsThis 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.