在wpf中禁用文本框中的快捷命令,保留击键检测

本文关键字:命令 保留 检测 wpf 文本 | 更新日期: 2023-09-27 18:07:06

我正在尝试一种方法来捕获WPF应用程序中的文本框中的键组合。到目前为止编写的代码(我在另一个讨论中发现)帮助我做到了这一点,除了那些链接到快捷命令的组合(Ctrl+C, Ctrl+V, Ctrl+X…)。我想捕捉用户按下文本框的所有键(空格,删除,退格和上面的所有组合)。这是代码:

int MaxKeyCount = 3;
List<Key> PressedKeys = new List<Key>();
private void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Handled) return;
        //Check all previous keys to see if they are still pressed
        List<Key> KeysToRemove = new List<Key>();
        foreach (Key k in PressedKeys)
        {
            if (!Keyboard.IsKeyDown(k))
                KeysToRemove.Add(k);
        }
        //Remove all not pressed keys
        foreach (Key k in KeysToRemove)
            PressedKeys.Remove(k);
        //Add the key if max count is not reached
        if (PressedKeys.Count < MaxKeyCount)
            //Add the key if it is part of the allowed keys
            //if (AllowedKeys.Contains(e.Key))
            if (!PressedKeys.Contains(e.Key))
                PressedKeys.Add(e.Key);
        PrintKeys();
        e.Handled = true;
    }
    private void PrintKeys()
    {
        //Print all pressed keys
        string s = "";
        if (PressedKeys.Count == 0) return;
        foreach (Key k in PressedKeys)
            if (IsModifierKey(k))
                s += GetModifierKey(k) + " + ";
            else
                s += k + " + ";
        s = s.Substring(0, s.Length - 3);
        TextBox.Text = s;
    }
    private bool IsModifierKey(Key k)
    {
        if (k == Key.LeftCtrl || k == Key.RightCtrl ||
            k == Key.LeftShift || k == Key.RightShift ||
            k == Key.LeftAlt || k == Key.RightAlt ||
            k == Key.LWin || k == Key.RWin)
            return true;
        else
            return false;
    }
    private ModifierKeys GetModifierKey(Key k)
    {
        if (k == Key.LeftCtrl || k == Key.RightCtrl)
            return ModifierKeys.Control;
        if (k == Key.LeftShift || k == Key.RightShift)
            return ModifierKeys.Shift;
        if (k == Key.LeftAlt || k == Key.RightAlt)
            return ModifierKeys.Alt;
        if (k == Key.LWin || k == Key.RWin)
            return ModifierKeys.Windows;
        return ModifierKeys.None;
    }

有人有禁用快捷命令的想法,保留按键?谢谢!

在wpf中禁用文本框中的快捷命令,保留击键检测

我认为这些可以使用自定义CommandBindings使用相应的应用程序命令覆盖。

设置句柄中的"ExecutedRoutedEventArgs.Handled"为"true"。

另外:从可用性的角度来说,这是一个坏主意。


的例子:

<TextBox>
    <TextBox.CommandBindings>
        <CommandBinding Command="Paste" Executed="CommandBinding_Executed"/>
    </TextBox.CommandBindings>
</TextBox>
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
    e.Handled = true;
}

这可能不是最优雅的解决方案,但它适用于我。我需要一个文本框,接受所有的输入键而不触发快捷键命令,这样用户就可以改变热键为任何他们想要的

class NoShortcutTextBox : TextBox
{
    /// <summary>
    /// Occurs when a key is pressed while focus is on this element. Apply to all shortcuts like
    /// Ctrl-C or Ctrl-V
    /// </summary>
    public new event KeyEventHandler KeyDown;
    public NoShortcutTextBox()
    {
        CommandManager.AddPreviewCanExecuteHandler(this, CanExecute);
        // Workaround as we cannot raise event in base class, so we hide it and use
        // our version of KeyDown instead
        base.KeyDown += (sender, e) => KeyDown(sender, e);
        // --Demo--
        KeyDown += (sender, e) =>
        {
            // Fetch the actual shortcut key
            var key = (e.Key == Key.System ? e.SystemKey : e.Key);
            if (key == Key.LeftShift || key == Key.RightShift
            || key == Key.LeftCtrl || key == Key.RightCtrl
            || key == Key.LeftAlt || key == Key.RightAlt
            || key == Key.LWin || key == Key.RWin) return;
            var sb = new StringBuilder();
            if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control))
            {
                sb.Append("Ctrl+");
            }
            if (Keyboard.Modifiers.HasFlag(ModifierKeys.Shift))
            {
                sb.Append("Shift+");
            }
            if (Keyboard.Modifiers.HasFlag(ModifierKeys.Alt))
            {
                sb.Append("Alt+");
            }
            Console.WriteLine(sb.Append(key.ToString()).ToString());
        };
    }
    private void CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.Handled = true;
        if (!(e.Command is RoutedUICommand command)) return;
        switch (command.Text)
        {
            case "Copy":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.C));
                break;
            case "Cut":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.X));
                break;
            case "Paste":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.V));
                break;
            case "Select All":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.A));
                break;
            case "Undo":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Z));
                break;
            case "Redo":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Y));
                break;
            case "Backspace":
            case "DeletePreviousWord":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Back));
                break;
            case "Delete":
            case "DeleteNextWord":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Delete));
                break;
            case "MoveToLineStart":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Home));
                break;
            case "MoveToLineEnd":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.End));
                break;
            case "ToggleInsert":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Insert));
                break;
            case "MoveUpByPage":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.PageUp));
                break;
            case "MoveDownByPage":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.PageDown));
                break;
            case "MoveLeftByCharacter":
            case "MoveLeftByWord":
            case "SelectLeftByWord":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Left));
                break;
            case "MoveRightByCharacter":
            case "MoveRightByWord":
            case "SelectRightByWord":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Right));
                break;
            case "MoveDownByLine":
            case "MoveDownByParagraph":
            case "SelectDownByParagraph":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Down));
                break;
            case "MoveUpByLine":
            case "MoveUpByParagraph":
            case "SelectUpByParagraph":
                KeyDown?.Invoke(this, GetKeyEventArgs(Key.Up));
                break;
        }
    }
    private KeyEventArgs GetKeyEventArgs(Key key)
    {
        return new KeyEventArgs(
            Keyboard.PrimaryDevice,
            new HwndSource(0, 0, 0, 0, 0, "", IntPtr.Zero), // dummy source
            0,
            key)
        {
            RoutedEvent = TextBox.KeyDownEvent,
        };
    }
}

你可以在PreviewKeyDown事件中用e.Handled=true删除任何按键动作或做任何其他动作:

    private void yourControl_PreviewKeyDown(object sender, KeyEventArgs e) {
        // Remove shortcut for Ctrl+C
        if ((Keyboard.Modifiers & ModifierKeys.Control) != ModifierKeys.Control && e.Key == Key.C)
            e.Handled = true;
    }