Posted in

Hotkey Editor Controle no WPF • Oleksii Holub

Hotkey Editor Controle no WPF • Oleksii Holub

Às vezes, os aplicativos da GUI oferecem uma maneira de os usuários configurarem teclas de atalho, normalmente usando uma caixa de texto que registra uma combinação de teclas pressionadas dentro dela. Esse controle não sai da caixa no WPF, mas podemos implementá -lo.

Classe de tecla de atalho

O WPF tem duas enumerações úteis para esta tarefa – System.Windows.Input.Key e System.Windows.Input.ModifierKeys. Vamos fazer uma aula que encapsula os valores dessas enumes e chame Hotkey.

public class Hotkey
{
    public Key Key { get; }

    public ModifierKeys Modifiers { get; }

    public Hotkey(Key key, ModifierKeys modifiers)
    {
        Key = key;
        Modifiers = modifiers;
    }

    public override string ToString()
    {
        var str = new StringBuilder();

        if (Modifiers.HasFlag(ModifierKeys.Control))
            str.Append("Ctrl + ");
        if (Modifiers.HasFlag(ModifierKeys.Shift))
            str.Append("Shift + ");
        if (Modifiers.HasFlag(ModifierKeys.Alt))
            str.Append("Alt + ");
        if (Modifiers.HasFlag(ModifierKeys.Windows))
            str.Append("Win + ");

        str.Append(Key);

        return str.ToString();
    }
}

Uma instância desta classe é criada especificando uma chave junto com uma combinação de modificadores (se houver) que precisam ser pressionados para executar um atalho.

ToString() O método será chamado pelo WPF para exibir uma instância da classe dentro de uma caixa de texto se não houver conjunto de conversor. Também é usado pelo Visual Studio quando a depuração, o que o torna mais conveniente. Este método gerará uma string que representa a tecla de atalho atual, por exemplo Ctrl + Alt + K.

Controle do usuário do WPF

Para fazer o controle real do WPF, você pode derivar de TextBox ou envolvê -lo por conta própria UserControl. Eu escolhi o último, principalmente por dois motivos:

  • É possível ocultar todas as propriedades inerentes à caixa de texto que não são aplicáveis ​​ao meu controle
  • Existem menos limitações no caso de eu precisar substituir a caixa de texto por um controle diferente ou adicionar algo sobre ela
<UserControl x:Class="Your.Namespace.HotkeyEditorControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             x:Name="UserControl"
             d:DesignHeight="300"
             d:DesignWidth="300"
             mc:Ignorable="d">
    <TextBox x:Name="HotkeyTextBox"
             HorizontalContentAlignment="Center"
             VerticalContentAlignment="Center"
             IsReadOnly="True"
             IsReadOnlyCaretVisible="False"
             IsUndoEnabled="False"
             PreviewKeyDown="HotkeyTextBox_PreviewKeyDown"
             Text="{Binding Hotkey, ElementName=UserControl, Mode=OneWay, TargetNullValue=&lt; not set &gt;}">
        <TextBox.ContextMenu>
            <ContextMenu Visibility="Collapsed" />
        </TextBox.ContextMenu>
    </TextBox>
</UserControl>

Existem algumas coisas importantes que precisamos configurar em nosso interno TextBox. Primeiro, não deve permitir a entrada de texto manual, então eu defino IsReadOnly para true.

Segundo, seria melhor remover o cuidador, pois não é útil de forma alguma. Contexto IsReadOnlyCaretVisible para false cuida disso.

Também não queremos que ele mantenha o histórico de desfazer/refazer, então vamos desativar IsUndoEnabled também.

Por fim, as caixas de texto WPF têm um menu de contexto padrão com botões como copiar, cortar, colar etc. que também não precisamos. Podemos desativá -lo definindo a visibilidade do menu como Collapsed.

A propriedade de texto está ligada ao Hotkey propriedade usando o OneWay modo. O último é importante porque estamos definindo o valor de Hotkey De código-behind. Essa ligação é usada apenas para atualizar o texto dentro da caixa de texto.

Quanto ao código-behind, parece o seguinte:

public partial class HotkeyEditorControl
{
    public static readonly DependencyProperty HotkeyProperty =
        DependencyProperty.Register(
            nameof(Hotkey),
            typeof(Hotkey),
            typeof(HotkeyEditorControl),
            new FrameworkPropertyMetadata(
                default(Hotkey),
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault
            )
        );

    public Hotkey Hotkey
    {
        get => (Hotkey) GetValue(HotkeyProperty);
        set => SetValue(HotkeyProperty, value);
    }

    public HotkeyEditorControl()
    {
        InitializeComponent();
    }

    private void HotkeyTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        // Don't let the event pass further because we don't want
        // standard textbox shortcuts to work.
        e.Handled = true;

        // Get modifiers and key data
        var modifiers = Keyboard.Modifiers;
        var key = e.Key;

        // When Alt is pressed, SystemKey is used instead
        if (key == Key.System)
        {
            key = e.SystemKey;
        }

        // Pressing delete, backspace or escape without modifiers clears the current value
        if (modifiers == ModifierKeys.None &&
            (key == Key.Delete || key == Key.Back || key == Key.Escape))
        {
            Hotkey = null;
            return;
        }

        // If no actual key was pressed - return
        if (key == Key.LeftCtrl ||
            key == Key.RightCtrl ||
            key == Key.LeftAlt ||
            key == Key.RightAlt ||
            key == Key.LeftShift ||
            key == Key.RightShift ||
            key == Key.LWin ||
            key == Key.RWin ||
            key == Key.Clear ||
            key == Key.OemClear ||
            key == Key.Apps))
        {
            return;
        }

        // Update the value
        Hotkey = new Hotkey(key, modifiers);
    }
}

Para capturar as teclas que estamos processando o PreviewKeyDown Evento porque também nos permite desativar os atalhos de caixa de texto padrão, como copiar, cortar, pastar etc.

  1. Ele define e.Handled para true para que os eventos não passem mais pela corrente
  2. Extrai informações sobre a chave que foi pressionada
  3. Ele verifica se excluir, backspace ou escape foram pressionados e limpa a entrada se assim for

Finalmente, eis como o controle se parece no meu aplicativo, Lâmpada elétrica:

Hotkey Editor Controle no WPF • Oleksii Holub

Luis es un experto en Inteligência Empresarial, Redes de Computadores, Gestão de Dados e Desenvolvimento de Software. Con amplia experiencia en tecnología, su objetivo es compartir conocimientos prácticos para ayudar a los lectores a entender y aprovechar estas áreas digitales clave.

Leave a Reply

Your email address will not be published. Required fields are marked *

mightycash