Reputation: 2655
What do I have to use to be able to get "all keys" that are pressed on the keyboard at the moment? Since Form.KeyPress += new EventHandler()
doesn't do much at all when it's filled of controls. It doesn't call it no matter what I do, neither KeyDown, KeyUp or anything else... and yeah, I know how to use them.
So, if there's any function in the system that can check for pressed keys, that returns an array of the keys used or something - I would be grateful to be pointed in the right direction.
Upvotes: 8
Views: 19716
Reputation: 9861
I've expanded on JaredPar's answer a little bit. The following method returns the collection of all keys that are currently being pressed:
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Input;
private static readonly byte[] DistinctVirtualKeys = Enumerable
.Range(0, 256)
.Select(KeyInterop.KeyFromVirtualKey)
.Where(item => item != Key.None)
.Distinct()
.Select(item => (byte)KeyInterop.VirtualKeyFromKey(item))
.ToArray();
/// <summary>
/// Gets all keys that are currently in the down state.
/// </summary>
/// <returns>
/// A collection of all keys that are currently in the down state.
/// </returns>
public IEnumerable<Key> GetDownKeys()
{
var keyboardState = new byte[256];
GetKeyboardState(keyboardState);
var downKeys = new List<Key>();
for (var index = 0; index < DistinctVirtualKeys.Length; index++)
{
var virtualKey = DistinctVirtualKeys[index];
if ((keyboardState[virtualKey] & 0x80) != 0)
{
downKeys.Add(KeyInterop.KeyFromVirtualKey(virtualKey));
}
}
return downKeys;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetKeyboardState(byte[] keyState);
Upvotes: 6
Reputation: 45071
If you only need to know all keystrokes when your application is active, regardless which control within your application has the focus, than you can use the KeyPreview
property of your form.
Simply set the property to true and subscribe to the desired Key events on the form. Now you'll receive all keystrokes within your application before they are forwarded to the concrete control, allowing you to react on yourself on it and cancel its forwarding to the control be setting the Cancel
property to true.
If you need to receive the pressed keys while your application is not the active one, then you need some kind of low-level keyboard hook. I didn't test it, but this article on CodeProject looks quite promising for this case.
Upvotes: 1
Reputation: 754515
It sounds like you want to query the state of all keys in the keyboard. The best function for that is the Win32 API call GetKeyboardState
I don't believe there is a good managed equivalent of that function. The PInvoke code for it is fairly straight forward
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetKeyboardState(byte [] lpKeyState);
var array = new byte[256];
GetKeyboardState(array);
This will populate the byte[]
with the up / down state of every virtual key in the system. If the high bit is set then the virtual key is currently pressed. Mapping a Key
to a virtual key code is done by only considering the byte
portion of the numeric Key
value.
public static byte GetVirtualKeyCode(Key key) {
int value = (int)key;
return (byte)(value & 0xFF);
}
The above works for most of the Key
values but you need to be careful with modifier keys. The values Keys.Alt
, Keys.Control
and Keys.Shift
won't work here because they're technically modifiers and not key values. To use modifiers you need to use the actual associated key values Keys.ControlKey
, Keys.LShiftKey
, etc ... (really anything that ends with Key)
So checking if a particular key is set can be done as follows
var code = GetVirtualKeyCode(Key.A);
if ((array[code] & 0x80) != 0) {
// It's pressed
} else {
// It's not pressed
}
Upvotes: 17
Reputation: 203802
I believe you are looking for the PreviewKeyDown event which will fire if a key is pressed while the form has focus, even if another child control within that form currently has focus.
Upvotes: 0