There are several keys on the keyboard that can be in a toggled state: num lock, scroll lock, cap lock and insert. There is a convenient method in the Control class that will get the state of the button: Control.IsKeyLocked(key). The key parameter can be one of Keys.CapLock, Keys.NumLock, Keys.Scroll and Keys.Insert. The method returns true if the key is in the toggled state, otherwise it returns false.
According to the MSDN documentation, the method will throw a NotSupportedException if the key is not CapLock, NumLock or Scroll; however, Insert also works and does not throw an exception.
This technique has been available since .NET 2.0.
For older .NET versions, it was necessary to do some interop with the user32.dll. There is a method that returns a bit field for the state of a key. For keys that can be toggled, the lowest bit in the field will be 1. Use a bitwise & operation to isolate the bit.
[System.Runtime.InteropServices.DllImport("user32.dll")] private static extern ushort GetKeyState(int keyCode); //From winuser.h private const int VK_INSERT = 0x2D; private const int VK_NUMLOCK = 0x90; private const int VK_SCROLL = 0x91; private const int VK_CAPITAL = 0x14; public static bool IsKeyToggled(int nKey) { return (GetKeyState(nKey) & 0x01) == 1; }
The hex codes for the keys can be obtained from winuser.h. In VS08, I found this file under the SDK folder for smart phones and pocket PC.
This technique is not limited to the keys that can be toggled. The state of any key can be tested.
This technique also works for testing if the key is up or down. If bit number 8 is a 1 then the key is down, otherwise it is up.
public static bool IsKeyDown(int nKey) { return (GetKeyState(nKey) & 0x80) == 0x80; }
For Vista and Windows 7, the interop seems to have been encapsulated. There is a Keyboad class that is part of the System.Windows.Input namespace. References to the PresentationCore and to the WindowsBase dll's must be made. The PresentationCore contains the Keyboard and Keystate classes. The WindowsBase contains the Key class. Be careful with the Key class, since there is also a Key class in System.Windows.Forms.
The WindowsBase reference might not be in the list of available .NET references. To find the dll, browse to
/Program File/Reference Assemblies/Microsoft/Framework/v3.0/WindowsBase.dll
There are several classes that are in both System.Windows.Input and System.Windows.Forms, like Cursor and MouseEventArgs. The inability to specify class names in a using statement causes a problem here. You must use the fully qualified name for classes that are in both references, or only use one of the imports and use the fully qualified name for all classes in that reference.
Keyboard.GetKeyStates(Key.CapsLock) == KeyStates.Toggled
There are additional methods in the class that can test the state of any key with IsKeyDown
and IsKeyUp
.
if (Keyboard.IsKeyDown(Key.Z)) { ... }