I wanted to make user to customise the shortcut keys, so I'm using a textbox to get the key input. The expected state should be to save the key when pressed, and show KeyGesture string when released.
But some keys will be responded to by other registered hotkeys ( like Ctrl A, win G etc. ) , unable to determine whether if the keys are all released, so that cannot clear ModifierKeys when appropriate.
Here's my code, if input a registered hotkey this keyCount will be wrong:
KeyGestureConverter keyGestureConverter = new KeyGestureConverter();
Key key;
ModifierKeys modifierKeys;
int keyCount = 0;
private void HotKeyTextbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.LeftCtrl) || e.Key.Equals(Key.RightCtrl))
modifierKeys |= ModifierKeys.Control;
else if (e.Key.Equals(Key.LeftAlt) || e.Key.Equals(Key.RightAlt))
modifierKeys |= ModifierKeys.Alt;
else if (e.Key.Equals(Key.LeftShift) || e.Key.Equals(Key.RightShift))
modifierKeys |= ModifierKeys.Shift;
else if (e.Key.Equals(Key.LWin) || e.Key.Equals(Key.RWin))
modifierKeys |= ModifierKeys.Windows;
else
key = e.Key;
keyCount ;
}
private void HotKeyTextbox_KeyUp(object sender, KeyEventArgs e)
{
keyCount--;
try
{
KeyGesture keyGesture = new KeyGesture(key, modifierKeys);
HotKeyTextbox.Text = keyGestureConverter.ConvertToString(keyGesture);
}
catch
{
HotKeyTextbox.Text = string.Empty;
}
if (keyCount <= 0)
{
keyCount = 0;
key = Key.None;
modifierKeys = ModifierKeys.None;
}
}
How about achieving the right effect?
CodePudding user response:
EDIT : misunderstood the question, this is for when shortcuts have already been recorded.
private void Key_Down(object sender, System.Windows.Input.KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.Control) // With CTRL
{
switch (e.Key)
{
case Key.Escape:
Close();
break;
case Key.Y:
Validate_Data();
break;
}
}
else // Without CRTL
{
switch (e.Key)
{
case Key.Escape:
Close();
break;
}
}
}
CodePudding user response:
You must handle the PreviewKeyDown
and PreviewKeyUp
events to catch common key gestures before they got handled by the TextBox
. TextBox
will handle certain gestures like "Ctrl C" and then mark the event as handled.
To print a key combination simply use the KeyGesture.GetDisplayStringForCulture
method (see example below).
To register a handler for the recorded gesture, simply define new KeyBinding
and add it to the appropriate UIElement.InputBindings
collection. But to make sense, you would have to let the user select the key command (action) first. Otherwise you don't know to which action the gesture should map to.
The following example assumes that the selected action is already stored in the SelectedGestureCommand
property.
To handle/override globally registered key gestures like your mentioned "Windows G", you would have to use P/Invoke to handle those events on OS level. There is no WPF API for this task.
MainWindow.xaml
<TextBox PreviewKeyDown="RecordGesture_OnKeyDown"
PreviewKeyUp="PrintRecordedGesture_OnKeyUp" />
MainWindow.xamlcs
public MainWindow()
{
InitializeComponent();
// Register the predefined gestures that the user can later modify.
// TODO::Define the required commands by implementing ICommand for each
this.InputBindings.Add(new KeyBinding(DoSomethingCommand, Key.A, ModifierKeys.Shift | ModifierKeys.Alt));
}
private void RecordGesture_OnKeyDown(object sender, KeyEventArgs e)
{
var newGesture = new KeyGesture(e.Key, e.KeyboardDevice.Modifiers);
// Update the existing action with the new gesture
KeyBinding selectedKeyBinding = this.InputBindings
.OfType<KeyBinding>()
.First(keyBinding => keyBinding.Command == this.SelectedGestureCommand);
selectedKeyBinding.Gesture = newGesture;
}
private void PrintRecordedGesture_OnKeyUp(object sender, KeyEventArgs e)
{
var currentGesture = new KeyGesture(e.Key, e.KeyboardDevice.Modifiers);
// Print the new gesture
(sender as TextBox).Text = currentGesture.GetDisplayStringForCulture(CultureInfo.CurrentCulture);
}