Capture Multiple Key Downs in C#

Capture multiple key downs in C#

I think you'll be best off when you use the GetKeyboardState API function.

[DllImport ("user32.dll")]
public static extern int GetKeyboardState( byte[] keystate );

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
byte[] keys = new byte[256];

GetKeyboardState (keys);

if ((keys[(int)Keys.Up] & keys[(int)Keys.Right] & 128 ) == 128)
{
Console.WriteLine ("Up Arrow key and Right Arrow key down.");
}
}

In the KeyDown event, you just ask for the 'state' of the keyboard.
The GetKeyboardState will populate the byte array that you give, and every element in this array represents the state of a key.

You can access each keystate by using the numerical value of each virtual key code. When the byte for that key is set to 129 or 128, it means that the key is down (pressed). If the value for that key is 1 or 0, the key is up (not pressed). The value 1 is meant for toggled key state (for example, caps lock state).

For details see the Microsoft documentation for GetKeyboardState.

Capturing ctrl + multiple key downs

The article in the comment may have been for WPF but the idea in it can still be used

Construct a class such as

    public class MultiKeyGesture
{
private List<Keys> _keys;
private Keys _modifiers;
public MultiKeyGesture(IEnumerable<Keys> keys, Keys modifiers)
{
_keys = new List<Keys>(keys);
_modifiers = modifiers;
if (_keys.Count == 0)
{
throw new ArgumentException("At least one key must be specified.", "keys");
}
}

private int currentindex;
public bool Matches(KeyEventArgs e)
{
if (e.Modifiers == _modifiers && _keys[currentindex] == e.KeyCode)
//at least a partial match
currentindex++;
else
//No Match
currentindex = 0;
if (currentindex + 1 > _keys.Count)
{
//Matched last key
currentindex = 0;
return true;
}
return false;
}
}

but ignore the inheritance.

to use it

    private MultiKeyGesture Shortcut1 = new MultiKeyGesture(new List<Keys> { Keys.A, Keys.B }, Keys.Control);
private MultiKeyGesture Shortcut2 = new MultiKeyGesture(new List<Keys> { Keys.C, Keys.D }, Keys.Control);
private MultiKeyGesture Shortcut3 = new MultiKeyGesture(new List<Keys> { Keys.E, Keys.F }, Keys.Control);

protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (Shortcut1.Matches(e))
BackColor = Color.Green;
if (Shortcut2.Matches(e))
BackColor = Color.Blue;
if (Shortcut3.Matches(e))
BackColor = Color.Red;
}

Multiple keys in KeyDown

Key enumeration is not marked with Flags and so cannot hold multiple values. And there is just one Key property in that event args, so just one key. Hence, your if can never be true because 3 of your && conditions are mutually exclusive.

What you can do instead is this:

if ((Keyboard.Modifiers == ModifierKeys.Control)
&& (Keyboard.IsKeyDown(Key.R))
&& (Keyboard.IsKeyDown(Key.S))
&& (Keyboard.IsKeyDown(Key.V))) {

}

Note that if you want to allow other modifier keys to be pressed at the same time (so, if you don't care if both ALT and CONTROL might be pressed together for example), then you should use

Keyboard.Modifiers.HasFlag(ModifierKeys.Control)

instead.

multiple keys keydown on keyboard at once time in c#

You can't get a KeyDown event with multiple keys.

However, you can either check for keys that are currently pressed, or you can keep track of all those that are Down at the moment (record them when you get KeyDown and remove when you get KeyUp).

There is a fixed limit to keys being pressed simultaneously based on the hardware keyboard. It may very well be that some key combinations only allow you to register two keys simultaneously, while others are more useable. And of course, there's gaming keyboards that can easily keep track of 20 or more at a time.

How to detect if multiple keys are pressed in C# forms

The source of the problems is that this simple request is simply not supported under Winforms.

Sounds weird? It is. Winforms is often painfully close to the hardware layers and while this may be quite interesting at times, it also may be just a pita..

((One hidden hint by Hans should be noted: In the KeyUp you get told which key was released so you can keep track of as many keys as you want..))

But now for a direct solution that desn't require you to keep a bunch of bools around and manage them in the KeyDown and KeyUp events..: Enter Keyboard.IsKeyDown.

With it code like this works:

Uses the Keyboard.IsKeyDown to determine if a key is down.
e is an instance of KeyEventArgs.

if (Keyboard.IsKeyDown(Key.Return)) {
btnIsDown.Background = Brushes.Red; }
...

Of course you can ceck for multiple key as well:

if (Keyboard.IsKeyDown(Key.A) && Keyboard.IsKeyDown(Key.W)) ...

The only requirement is that you borrow this from WPF:

First: Add the namespace:

using System.Windows.Input;

Then: Add two references to the project:

PresentationCore
WindowsBase

Sample Image

Now you can test the keyboard at any time, including the KeyPress event..

Tracking KeyUp and KeyDown of multiple keys at once

I'm not sure whether I understand your question, but I would use a Dictionary<Keys, Stopwatch> to track the times. As keys for the Dictionary I would use the lower-case character of each pressed key.

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private readonly Dictionary<Keys, Stopwatch> _stopwatches = new Dictionary<Keys, Stopwatch>();

private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
_stopwatches[e.KeyCode] = Stopwatch.StartNew();
}

private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
textBox2.Text += e.KeyCode;

Stopwatch stopwatch;
if (_stopwatches.TryGetValue(e.KeyCode, out stopwatch))
{
stopwatch.Stop();
textBox2.Text += " " + stopwatch.ElapsedMilliseconds + "ms";
}

textBox2.Text += Environment.NewLine;
}
}

textBox1 is the input box.
textBox2 is the output box, but you could use your text file here as well.



Related Topics



Leave a reply



Submit