简体   繁体   English

WPF 确定文本框中释放的所有键?

[英]WPF determine all keys released in textbox?

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.预期的 state 应该是在按下时保存键,并在释放时显示 KeyGesture 字符串。

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.但有些按键会被其他注册的热键(如Ctrl+A、win+G等)响应,无法判断按键是否全部释放,因此无法在适当的时候清除ModifierKeys。

Here's my code, if input a registered hotkey this keyCount will be wrong:这是我的代码,如果输入一个注册的热键,这个keyCount将是错误的:

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?如何达到正确的效果?

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;
        }
    }
}

You must handle the PreviewKeyDown and PreviewKeyUp events to catch common key gestures before they got handled by the TextBox .您必须处理PreviewKeyDownPreviewKeyUp事件,以便在它们被TextBox处理之前捕获常见的按键手势。 TextBox will handle certain gestures like "Ctrl+C" and then mark the event as handled. TextBox将处理某些手势,例如“Ctrl+C”,然后将事件标记为已处理。

To print a key combination simply use the KeyGesture.GetDisplayStringForCulture method (see example below).要打印组合键,只需使用KeyGesture.GetDisplayStringForCulture方法(参见下面的示例)。
To register a handler for the recorded gesture, simply define new KeyBinding and add it to the appropriate UIElement.InputBindings collection.要为录制的手势注册处理程序,只需定义新的KeyBinding并将其添加到适当的UIElement.InputBindings集合中。 But to make sense, you would have to let the user select the key command (action) first.但要有意义,您必须先让用户 select 键入命令(操作)。 Otherwise you don't know to which action the gesture should map to.否则你不知道手势应该 map 到哪个动作。
The following example assumes that the selected action is already stored in the SelectedGestureCommand property.以下示例假定所选操作已存储在SelectedGestureCommand属性中。

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.要处理/覆盖全局注册的按键手势,如您提到的“Windows+G”,您必须使用 P/Invoke 在操作系统级别处理这些事件。 There is no WPF API for this task.此任务没有 WPF API。

MainWindow.xaml主窗口.xaml

<TextBox PreviewKeyDown="RecordGesture_OnKeyDown"
         PreviewKeyUp="PrintRecordedGesture_OnKeyUp" />

MainWindow.xamlcs主窗口.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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM