In my application, I want to let users customize keyboard shortcuts, just like it's done in Visual Studio's keyboard options. The user can focus a blank text box and then type any shortcut he wants to assign to a command.
The closest I've come to make it work is by subscribing to the TextBox.PreviewKeyDown event, setting it as handled to prevent actual text input in the text box. I then ignore the KeyDown events associated with modifier keys (is there a cleaner way to determine if a Key is a modifier key?).
// Code-behind
private void ShortcutTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
// The text box grabs all input
e.Handled = true;
if (e.Key == Key.LeftCtrl ||
e.Key == Key.RightCtrl ||
e.Key == Key.LeftAlt ||
e.Key == Key.RightAlt ||
e.Key == Key.LeftShift ||
e.Key == Key.RightShift)
return;
string shortcutText = "";
if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
shortcutText += "Ctrl+";
if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
shortcutText += "Shift+";
if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt)
shortcutText += "Alt+";
_ShortcutTextBox.Text = shortcutText + e.Key.ToString();
}
The above works for any shortcut starting with Ctrl and Ctrl+Shift, but fails for any Alt shortcuts. The e.Key is always set to Key.System
when I press a shortcut containing Alt.
How can I record Alt shortcuts from the user? Is there a better, more robust way to record shortcuts form the user?
Best Answer
The trick is to use the SystemKey property if the Key property is set to
Key.System
:I added the left and right
Windows
keys to the modifier list, because they sometimes appeared in the shortcut key name when a complex (Ctrl+Shift+Alt
) key combination was typed from a Terminal Server session. They're never present inKeyboard.Modifiers
, though, since they're reserved for global shortcuts, so I don't handle them there.I also used a StringBuilder to avoid creating too many
string
instances.This solution works with any key combination, except
Shift+Alt
(theAlt
modifier is not seen in that case). That might be an artifact of my Terminal Server environment, though, so your mileage may vary.Finally, I added a
_File
menu to the window to see what would happen, and theAlt+F
shortcut key is effectively trapped by the text box before it reaches the menu, which seems to be what you want.