Reputation: 995
I have searched for how to detect keyboard combinations in c#.
As of this I use the KeyDown
Event of the Form with KeyPreview = true
.
I need to check if the e.Modifiers
is any Modifier and e.KeyCode
is something else than a Modifier.
The best would be a really open statement like:
if(Keys.Modifiers.Contains(e.Modifiers) && !Keys.Modifiers.Contains(e.KeyCode)){}
Sadly this is not working.
This is not working too, it gets true with all of the modifier keys.
if ((e.Modifiers == Keys.Alt || e.Modifiers == Keys.Control || e.Modifiers == Keys.Shift)
&& (e.KeyCode != Keys.Alt && e.KeyCode != Keys.Control && e.KeyCode != Keys.Shift))
This is almost working, but as there is no Keys.AltKey
it gets true when ALT is clicked.
if ((e.Modifiers == Keys.Alt || e.Modifiers == Keys.Control || e.Modifiers == Keys.Shift)
&& (e.KeyCode != Keys.Alt && e.KeyCode != Keys.ControlKey && e.KeyCode != Keys.ShiftKey))
How could I achive this?
It should be possible that e.KeyCode
could be anything than a Modifier.
The reason: I need to give the user the possibility of pressing any key-combination with at least ONE modifier and at least ONE other key.
After getting the statement correctly, how is the best way to save the combination in a variable and check it when entered again? I thought about something like saving every entered key (when one is a Modifier and the other not) in a List<Keys>
and check it through a foreach
which return false;
when one key of the entered combination is not in the List.
Everything should be as dynamically as possible.
How could this be extended to check any combination? Like Ctrl + F + Shift + C
or Ctrl + F + H
Thanks!
Michael
Upvotes: 2
Views: 1737
Reputation: 9479
I think you may to have to do as John Wu suggest or at least some low level way as you will have to remember the last key pressed. If you use “multiple” CHARACTER keys… NOT modifier keys then you will have to remember what the last key combination was. For example: Ctrl + F + Shift + C
… you would have to remember the Ctrl + F + Shift
part first before you can look for the “C” character.
Anytime you use multiple “Character” keys you have to remember the first key(s) in the sequence. I am not sure if using this many keys to accomplish something would be that user friendly. However one possible solution which came from @Vivelin at How to get a combination of keys in c# seems to do the trick. It looks messy and with only two different conditions.
Using your example let’s say we are looking for the combination Ctrl + F + Shift + C
The code basically sets a Boolean value to true when the first part of the combination is met Ctrl + F + Shift
then it exits. When the next key is pressed and the combination is Ctrl + Shift + C
then you will know this combination Ctrl + F + Shift + C
has been met. This is similar to other programs where you hold down a control key(s) then press one character then another character not necessarily at the same time. In the code below I used a disabled text box to output when the combination is fired. I hope this helps.
private bool keyCombo1 = false;
private bool keyCombo2 = false;
private void textBox1_KeyDown(object sender, KeyEventArgs e) {
if (e.Control) {
if (e.Shift) {
if (e.KeyCode == Keys.F) {
keyCombo1 = true;
}
else {
if (e.KeyCode == Keys.C && keyCombo1) {
textBox2.AppendText("Key Combo 1 hit" + Environment.NewLine);
}
else {
keyCombo1 = false;
}
}
}
else {
// control only no-shift
if (e.KeyCode == Keys.F) {
keyCombo2 = true;
}
else {
if (e.KeyCode == Keys.H && keyCombo2) {
textBox2.AppendText("Key Combo 2 hit" + Environment.NewLine);
}
else {
keyCombo2 = false;
}
}
}
}
else {
// no control key pressed
}
}
Upvotes: 0
Reputation: 52280
Probably the cleanest way to accomplish this is to use a more low level API to obtain an array of every key that is currently pressed. This is going to make your logic a lot easier, but you'll have to do some fancy imports.
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetKeyboardState(byte [] lpKeyState);
var array = new byte[256];
GetKeyboardState(array);
Once you have the array, you can scan all the keys at the same time without any more O/S calls, which should create much less overhead.
For example, you can see how many keys are being pressed with something like
int countKeys = array.Count(a => a & 0x80);
If you just want to check if the left alt key is pressed, you can use
bool leftAlt = (array[(byte)Key.LeftAlt] & 0x80);
Upvotes: 1