À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=< not set >}">
<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.
- Ele define
e.Handled
paratrue
para que os eventos não passem mais pela corrente - Extrai informações sobre a chave que foi pressionada
- 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:

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.