Share via


Aceleradores de teclado

Hero image of the Surface keyboard

As teclas de aceleração (ou aceleradores de teclado) são atalhos de teclado que melhoram a usabilidade e a acessibilidade de seus aplicativos do Windows, fornecendo uma maneira intuitiva para os usuários invocarem ações ou comandos comuns sem navegar na interface do usuário do aplicativo.

Observação

Um teclado é indispensável para usuários com certas deficiências (consulte Acessibilidade do teclado), e também é uma ferramenta importante para usuários que o preferem como uma maneira mais eficiente de interagir com um aplicativo.

Consulte o tópico Teclas de acesso para obter detalhes sobre como navegar na interface do usuário de um aplicativo do Windows com atalhos de teclado.

Para criar seus próprios atalhos de teclado personalizados, consulte o tópico Eventos de teclado.

Visão geral

Os aceleradores são compostos por dois tipos de chaves: modificadores e não modificadores. As teclas modificadoras incluem Shift, Menu, Control e a tecla Windows, que são expostas por meio de VirtualKeyModifiers. Os não-modificadores incluem qualquer VirtualKey, como Delete, F3, Barra de espaço, Arrow, Esc e todas as teclas alfanuméricas e de pontuação.

Observação

Os aceleradores normalmente incluem as teclas de função F1 a F12 ou alguma combinação de uma tecla padrão emparelhada com uma ou mais teclas modificadoras (CTRL, Shift). Por exemplo, se um usuário pressionar Ctrl+Shift+M, a estrutura verificará os modificadores (Ctrl e Shift) e acionará o acelerador, se ele existir.

Muitos controles XAML têm aceleradores de teclado internos. Por exemplo, ListView oferece suporte a Ctrl+A para selecionar todos os itens na lista e RichEditBox oferece suporte a Ctrl+Tab para inserir uma guia na caixa de texto. Esses aceleradores de teclado integrados são chamados de aceleradores de controle e são executados somente se o foco estiver no elemento ou em um de seus filhos. Os aceleradores definidos por você usando as APIs de acelerador de teclado discutidas aqui são chamados de aceleradores de aplicativo.

Os aceleradores de teclado não estão disponíveis para todas as ações, mas geralmente estão associados a comandos expostos em menus (e devem ser especificados com o conteúdo do item de menu). Os aceleradores também podem ser associados a ações que não têm itens de menu equivalentes. No entanto, como os usuários dependem dos menus de um aplicativo para descobrir e aprender o conjunto de comandos disponível, você deve tentar tornar a descoberta de aceleradores o mais fácil possível (usar rótulos ou padrões estabelecidos pode ajudar nisso).

Um acelerador se repete automaticamente (por exemplo, quando o usuário pressiona Ctrl+Shift e, em seguida, mantém pressionada a tecla M, o acelerador é chamado repetidamente até que M seja liberado). Esse comportamento não pode ser modificado.

Screenshot of keyboard accelerators in a menu item label.
Aceleradores de teclado descritos em um rótulo de item de menu

Quando usar aceleradores de teclado

Recomendamos que você especifique aceleradores de teclado sempre que apropriado em sua interface do usuário e ofereça suporte a aceleradores em todos os controles personalizados.

  • Os aceleradores de teclado tornam seu aplicativo mais acessível para usuários com deficiências motoras, incluindo aqueles usuários que podem pressionar apenas uma tecla de cada vez ou têm dificuldade em usar um mouse.

    Uma interface do usuário de teclado bem projetada é um aspecto importante da acessibilidade do software. Ele permite que usuários com deficiência visual ou que tenham certas deficiências motoras naveguem em um aplicativo e interajam com seus recursos. Esses usuários podem não ser capazes de operar um mouse e, em vez disso, dependem de várias tecnologias assistivas, como ferramentas de aprimoramento do teclado, teclados na tela, ampliadores de tela, leitores de tela e utilitários de entrada de voz. Para esses usuários, a cobertura abrangente de comandos é crucial.

  • Os aceleradores de teclado tornam seu aplicativo mais utilizável para usuários avançados que preferem interagir por meio do teclado.

    Usuários experientes geralmente têm uma forte preferência pelo uso do teclado porque os comandos baseados no teclado podem ser inseridos mais rapidamente e não exigem que eles removam as mãos do teclado. Para esses usuários, eficiência e consistência são cruciais; A abrangência é importante apenas para os comandos mais utilizados.

Especificar um acelerador de teclado

Use as APIs do KeyboardAccelerator para criar aceleradores de teclado em aplicativos do Windows. Com essas APIs, você não precisa manipular vários eventos KeyDown para detectar a combinação de teclas pressionada e pode localizar aceleradores nos recursos do aplicativo.

Recomendamos que você defina aceleradores de teclado para as ações mais comuns em seu aplicativo e documente-as usando o rótulo de item de menu ou a dica de ferramenta. Neste exemplo, declaramos aceleradores de teclado somente para os comandos Renomear e Copiar.

<CommandBar Margin="0,200" AccessKey="M">
  <AppBarButton 
    Icon="Share" 
    Label="Share" 
    Click="OnShare" 
    AccessKey="S" />
  <AppBarButton 
    Icon="Copy" 
    Label="Copy" 
    ToolTipService.ToolTip="Copy (Ctrl+C)" 
    Click="OnCopy" 
    AccessKey="C">
    <AppBarButton.KeyboardAccelerators>
      <KeyboardAccelerator 
        Modifiers="Control" 
        Key="C" />
    </AppBarButton.KeyboardAccelerators>
  </AppBarButton>

  <AppBarButton 
    Icon="Delete" 
    Label="Delete" 
    Click="OnDelete" 
    AccessKey="D" />
  <AppBarSeparator/>
  <AppBarButton 
    Icon="Rename" 
    Label="Rename" 
    ToolTipService.ToolTip="Rename (F2)" 
    Click="OnRename" 
    AccessKey="R">
    <AppBarButton.KeyboardAccelerators>
      <KeyboardAccelerator 
        Modifiers="None" Key="F2" />
    </AppBarButton.KeyboardAccelerators>
  </AppBarButton>

  <AppBarButton 
    Icon="SelectAll" 
    Label="Select" 
    Click="OnSelect" 
    AccessKey="A" />
  
  <CommandBar.SecondaryCommands>
    <AppBarButton 
      Icon="OpenWith" 
      Label="Sources" 
      AccessKey="S">
      <AppBarButton.Flyout>
        <MenuFlyout>
          <ToggleMenuFlyoutItem Text="OneDrive" />
          <ToggleMenuFlyoutItem Text="Contacts" />
          <ToggleMenuFlyoutItem Text="Photos"/>
          <ToggleMenuFlyoutItem Text="Videos"/>
        </MenuFlyout>
      </AppBarButton.Flyout>
    </AppBarButton>
    <AppBarToggleButton 
      Icon="Save" 
      Label="Auto Save" 
      IsChecked="True" 
      AccessKey="A"/>
  </CommandBar.SecondaryCommands>

</CommandBar>

Screenshot of a keyboard accelerator in a tooltip.
Acelerador de teclado descrito em uma dica de ferramenta

O objeto UIElement tem uma coleção KeyboardAccelerator, KeyboardAccelerators, onde você especifica seus objetos KeyboardAccelerator personalizados e define os pressionamentos de tecla para o acelerador de teclado:

Observação

Os aceleradores de tecla única (A, Delete, F2, Barra de espaço, Esc, tecla multimídia) e os aceleradores de várias teclas (Ctrl+Shift+M) são suportados. No entanto, as teclas virtuais do Gamepad não são suportadas.

Aceleradores com escopo

Alguns aceleradores funcionam apenas em escopos específicos, enquanto outros funcionam em todo o aplicativo.

Por exemplo, o Microsoft Outlook inclui os seguintes aceleradores:

  • Ctrl+B, Ctrl+I e ESC funcionam apenas no escopo do formulário de envio de e-mail
  • Ctrl+1 e Ctrl+2 funcionam em todo o aplicativo

Menus de contexto

As ações do menu de contexto afetam apenas áreas ou elementos específicos, como os caracteres selecionados em um editor de texto ou uma música em uma lista de reprodução. Por esse motivo, recomendamos definir o escopo dos aceleradores de teclado para itens de menu de contexto como o pai do menu de contexto.

Use a propriedade ScopeOwner para especificar o escopo do acelerador de teclado. Este código demonstra como implementar um menu de contexto em um ListView com aceleradores de teclado com escopo:

<ListView x:Name="MyList">
  <ListView.ContextFlyout>
    <MenuFlyout>
      <MenuFlyoutItem Text="Share" Icon="Share"/>
      <MenuFlyoutItem Text="Copy" Icon="Copy">
        <MenuFlyoutItem.KeyboardAccelerators>
          <KeyboardAccelerator 
            Modifiers="Control" 
            Key="C" 
            ScopeOwner="{x:Bind MyList }" />
        </MenuFlyoutItem.KeyboardAccelerators>
      </MenuFlyoutItem>
      
      <MenuFlyoutItem Text="Delete" Icon="Delete" />
      <MenuFlyoutSeparator />
      
      <MenuFlyoutItem Text="Rename">
        <MenuFlyoutItem.KeyboardAccelerators>
          <KeyboardAccelerator 
            Modifiers="None" 
            Key="F2" 
            ScopeOwner="{x:Bind MyList}" />
        </MenuFlyoutItem.KeyboardAccelerators>
      </MenuFlyoutItem>
      
      <MenuFlyoutItem Text="Select" />
    </MenuFlyout>
    
  </ListView.ContextFlyout>
    
  <ListViewItem>Track 1</ListViewItem>
  <ListViewItem>Alternative Track 1</ListViewItem>

</ListView>

O atributo ScopeOwner do elemento MenuFlyoutItem.KeyboardAccelerators marca o acelerador como escopo em vez de global (o padrão é nulo ou global). Para obter mais detalhes, consulte a seção Resolvendo aceleradores mais adiante neste tópico.

Invocar um acelerador de teclado

O objeto KeyboardAccelerator usa o padrão de controle UIA (UIA (UIA Automation) para executar uma ação quando um acelerador é chamado.

A UIA [padrões de controle] expõe a funcionalidade de controle comum. Por exemplo, o controle Button implementa o padrão de controle Invoke para oferecer suporte ao evento Click (normalmente um controle é chamado clicando, clicando duas vezes ou pressionando Enter, um atalho de teclado predefinido ou alguma outra combinação de pressionamentos de tecla). Quando um acelerador de teclado é usado para invocar um controle, a estrutura XAML procura se o controle implementa o padrão de controle Invoke e, em caso afirmativo, o ativa (não é necessário ouvir o evento KeyboardAcceleratorInvoked).

No exemplo a seguir, Control+S dispara o evento Click porque o botão implementa o padrão Invoke.

<Button Content="Save" Click="OnSave">
  <Button.KeyboardAccelerators>
    <KeyboardAccelerator Key="S" Modifiers="Control" />
  </Button.KeyboardAccelerators>
</Button>

Se um elemento implementa vários padrões de controle, apenas um pode ser ativado por meio de um acelerador. Os padrões de controle são priorizados da seguinte forma:

  1. Invocar (botão)
  2. Alternar (caixa de seleção)
  3. Seleção (ListView)
  4. Expandir/Recolher (ComboBox)

Se nenhuma correspondência for identificada, o acelerador será inválido e uma mensagem de depuração será fornecida ("Nenhum padrão de automação para este componente encontrado. Implemente todo o comportamento desejado no evento Invoked. A configuração Manipulado como true no manipulador de eventos suprime essa mensagem.")

Comportamento personalizado do acelerador de teclado

O evento Invoked do objeto KeyboardAccelerator é acionado quando o acelerador é executado. O objeto de evento KeyboardAcceleratorInvokedEventArgs inclui as seguintes propriedades:

  • Manipulado (Booleano): Definir isso como true impede que o evento acione o padrão de controle e interrompa o borbulhamento do evento do acelerador. O padrão é false.
  • Element (DependencyObject): O objeto associado ao acelerador.
  • KeyboardAccelerator: O acelerador de teclado usado para gerar o evento Invoked.

Aqui demonstramos como definir uma coleção de aceleradores de teclado para itens em um ListView e como manipular o evento Invoked para cada acelerador.

<ListView x:Name="MyListView">
  <ListView.KeyboardAccelerators>
    <KeyboardAccelerator Key="A" Modifiers="Control,Shift" Invoked="SelectAllInvoked" />
    <KeyboardAccelerator Key="F5" Invoked="RefreshInvoked"  />
  </ListView.KeyboardAccelerators>
</ListView>
void SelectAllInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
  MyListView.SelectAll();
  args.Handled = true;
}

void RefreshInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
  MyListView.SelectionMode = ListViewSelectionMode.None;
  MyListView.SelectionMode = ListViewSelectionMode.Multiple;
  args.Handled = true;
}

Substituir o comportamento padrão do teclado

Alguns controles, quando têm foco, oferecem suporte a aceleradores de teclado internos que substituem qualquer acelerador definido pelo aplicativo. Por exemplo, quando um TextBox tem foco, o acelerador Control+C copia apenas o texto selecionado no momento (os aceleradores definidos pelo aplicativo são ignorados e nenhuma outra funcionalidade é executada).

Embora não seja recomendável substituir os comportamentos de controle padrão devido à familiaridade e às expectativas do usuário, você pode substituir o acelerador de teclado interno de um controle. O exemplo a seguir mostra como substituir o acelerador de teclado Control+C para um TextBox por meio do manipulador de eventos PreviewKeyDown :

 private void TextBlock_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
 {
    var ctrlState = CoreWindow.GetForCurrentThread().GetKeyState(Windows.System.VirtualKey.Control);
    var isCtrlDown = ctrlState == CoreVirtualKeyStates.Down || ctrlState 
        ==  (CoreVirtualKeyStates.Down | CoreVirtualKeyStates.Locked);
    if (isCtrlDown && e.Key == Windows.System.VirtualKey.C)
    {
        // Your custom keyboard accelerator behavior.
        
        e.Handled = true;
    }
 }

Desativar um acelerador de teclado

Se um controle estiver desabilitado, o acelerador associado também será desabilitado. No exemplo a seguir, como a propriedade IsEnabled do ListView está definida como false, o acelerador Control+A associado não pode ser invocado.

<ListView >
  <ListView.KeyboardAccelerators>
    <KeyboardAccelerator Key="A"
      Modifiers="Control"
      Invoked="CustomListViewSelecAllInvoked" />
  </ListView.KeyboardAccelerators>
  
  <TextBox>
    <TextBox.KeyboardAccelerators>
      <KeyboardAccelerator 
        Key="A" 
        Modifiers="Control" 
        Invoked="CustomTextSelecAllInvoked" 
        IsEnabled="False" />
    </TextBox.KeyboardAccelerators>
  </TextBox>

<ListView>

Os controles pai e filho podem compartilhar o mesmo acelerador. Nesse caso, o controle pai pode ser chamado mesmo se o filho tiver foco e seu acelerador estiver desabilitado.

Leitores de tela e aceleradores de teclado

Leitores de tela como o Narrador podem anunciar a combinação de teclas do acelerador de teclado aos usuários. Por padrão, esse é cada modificador (na ordem de enum VirtualModifiers) seguido pela chave (e separado por sinais de "+"). Você pode personalizar isso por meio da propriedade anexada AcceleratorKey AutomationProperties. Se mais de um acelerador for especificado, apenas o primeiro será anunciado.

Neste exemplo, o AutomationProperty.AcceleratorKey retorna a cadeia de caracteres "Control+Shift+A":

<ListView x:Name="MyListView">
  <ListView.KeyboardAccelerators>

    <KeyboardAccelerator 
      Key="A" 
      Modifiers="Control,Shift" 
      Invoked="CustomSelectAllInvoked" />
      
    <KeyboardAccelerator 
      Key="F5" 
      Modifiers="None" 
      Invoked="RefreshInvoked" />

  </ListView.KeyboardAccelerators>

</ListView>   

Observação

A configuração de AutomationProperties.AcceleratorKey não habilita a funcionalidade do teclado, apenas indica à estrutura UIA quais teclas são usadas.

Aceleradores de teclado comuns

Recomendamos que você torne os aceleradores de teclado consistentes em todos os aplicativos do Windows.

Os usuários precisam memorizar aceleradores de teclado e esperar os mesmos (ou semelhantes) resultados, mas isso nem sempre é possível devido às diferenças de funcionalidade entre os aplicativos.

Edição Acelerador de teclado comum
Iniciar o modo de edição Ctrl + E
Selecionar todos os itens em um controle ou janela focada Ctrl+A
Pesquisar e substituir CTRL + H
Desfazer CTRL+Z
Refaz Ctrl+Y
Excluir seleção e copiá-la para a área de transferência Ctrl + X
Copiar seleção para a área de transferência Ctrl + C, Ctrl + Inserir
Colar o conteúdo da área de transferência Ctrl + V, Shift + Inserir
Colar o conteúdo da área de transferência (com opções) Ctrl + Alt + V
Renomeia um item F2
Adicionar um novo item Ctrl + N
Adicionar um novo item secundário Ctrl + Shift + N
Excluir item selecionado (com desfazer) Del, Ctrl+D
Excluir item selecionado (sem desfazer) Shift + Del
Negrito Ctrl + B
Sublinhar Ctrl + U
Itálico Ctrl + I
Navegação
Localizar conteúdo em um controle focado ou em uma janela Ctrl +F
Ir para o próximo resultado da pesquisa F3
Outras ações
Adicionar favoritos Ctrl + D
Atualizar F5 ou Ctrl + R
Ampliar Ctrl + +
Reduzir Ctrl + -
Ampliar para o modo de exibição padrão Ctrl + 0
Salvar Ctrl + S
Fechar Ctrl + W
Imprimir Ctrl + P

Observe que algumas das combinações não são válidas para versões localizadas do Windows. Por exemplo, na versão em espanhol do Windows, Ctrl+N é usado para negrito em vez de Ctrl+B. Recomendamos fornecer aceleradores de teclado localizados se o aplicativo estiver localizado.

Funcionalidades de usabilidade para aceleradores de teclado

Dicas de ferramentas

Como os aceleradores de teclado normalmente não são descritos diretamente na interface do usuário do aplicativo do Windows, você pode melhorar a capacidade de descoberta por meio de dicas de ferramentas, que são exibidas automaticamente quando o usuário move o foco, pressiona e mantém pressionado ou passa o ponteiro do mouse sobre um controle. A dica de ferramenta pode identificar se um controle tem um acelerador de teclado associado e, em caso afirmativo, qual é a combinação de teclas do acelerador.

Windows 10, versão 1803 (atualização de abril de 2018) e mais recente

Por padrão, quando os aceleradores de teclado são declarados, todos os controles (exceto MenuFlyoutItem e ToggleMenuFlyoutItem) apresentam as combinações de teclas correspondentes em uma dica de ferramenta.

Observação

Se um controle tiver mais de um acelerador definido, apenas o primeiro será apresentado.

Screenshot of a Save button with a tool tip above it that indicates support for the Ctrl+S accelerator.
Combinação de teclas do acelerador na dica de ferramenta

Para objetos Button, AppBarButton e AppBarToggleButton, o acelerador de teclado é anexado à dica de ferramenta padrão do controle. Para objetos MenuFlyoutItem e ToggleMenuFlyoutItem, o acelerador de teclado é exibido com o texto do submenu.

Observação

A especificação de uma dica de ferramenta (consulte Button1 no exemplo a seguir) substitui esse comportamento.

<StackPanel x:Name="Container" Grid.Row="0" Background="AliceBlue">
    <Button Content="Button1" Margin="20"
            Click="OnSave" 
            KeyboardAcceleratorPlacementMode="Auto" 
            ToolTipService.ToolTip="Tooltip">
        <Button.KeyboardAccelerators>
            <KeyboardAccelerator  Key="A" Modifiers="Windows"/>
        </Button.KeyboardAccelerators>
    </Button>
    <Button Content="Button2"  Margin="20"
            Click="OnSave" 
            KeyboardAcceleratorPlacementMode="Auto">
        <Button.KeyboardAccelerators>
            <KeyboardAccelerator  Key="B" Modifiers="Windows"/>
        </Button.KeyboardAccelerators>
    </Button>
    <Button Content="Button3"  Margin="20"
            Click="OnSave" 
            KeyboardAcceleratorPlacementMode="Auto">
        <Button.KeyboardAccelerators>
            <KeyboardAccelerator  Key="C" Modifiers="Windows"/>
        </Button.KeyboardAccelerators>
    </Button>
</StackPanel>

Screenshot of three buttons labeled Button1, Button2, and Button3 with a tool tip above Button2 that indicates support for the Windows+B accelerator.

Combinação de teclas do acelerador anexada à dica de ferramenta padrão do Button

<AppBarButton Icon="Save" Label="Save">
    <AppBarButton.KeyboardAccelerators>
        <KeyboardAccelerator Key="S" Modifiers="Control"/>
    </AppBarButton.KeyboardAccelerators>
</AppBarButton>

Screenshot of a button with a Disk icon and a tool tip that includes the default Save text appended with the Ctrl+S accelerator in parentheses.

Combinação de teclas do acelerador anexada à dica de ferramenta padrão do AppBarButton

<AppBarButton AccessKey="R" Icon="Refresh" Label="Refresh" IsAccessKeyScope="True">
    <AppBarButton.Flyout>
        <MenuFlyout>
            <MenuFlyoutItem AccessKey="A" Icon="Refresh" Text="Refresh A">
                <MenuFlyoutItem.KeyboardAccelerators>
                    <KeyboardAccelerator Key="R" Modifiers="Control"/>
                </MenuFlyoutItem.KeyboardAccelerators>
            </MenuFlyoutItem>
            <MenuFlyoutItem AccessKey="B" Icon="Globe" Text="Refresh B" />
            <MenuFlyoutItem AccessKey="C" Icon="Globe" Text="Refresh C" />
            <MenuFlyoutItem AccessKey="D" Icon="Globe" Text="Refresh D" />
            <ToggleMenuFlyoutItem AccessKey="E" Icon="Globe" Text="ToggleMe">
                <MenuFlyoutItem.KeyboardAccelerators>
                    <KeyboardAccelerator Key="Q" Modifiers="Control"/>
                </MenuFlyoutItem.KeyboardAccelerators>
            </ToggleMenuFlyoutItem>
        </MenuFlyout>
    </AppBarButton.Flyout>
</AppBarButton>

Screenshot of a Menu with MenuFlyoutItems that include accelerator key combos.
Combinação de teclas do acelerador anexada ao texto de MenuFlyoutItem

Controle o comportamento da apresentação usando a propriedade KeyboardAcceleratorPlacementMode, que aceita dois valores: Auto ou Hidden.

<Button Content="Save" Click="OnSave" KeyboardAcceleratorPlacementMode="Auto">
    <Button.KeyboardAccelerators>
        <KeyboardAccelerator Key="S" Modifiers="Control" />
    </Button.KeyboardAccelerators>
</Button>

Em alguns casos, talvez seja necessário apresentar uma dica de ferramenta relativa a outro elemento (normalmente um objeto de contêiner).

Aqui, mostramos como usar a propriedade KeyboardAcceleratorPlacementTarget para exibir a combinação de teclas do acelerador de teclado para um botão Salvar com o contêiner Grade em vez do botão.

<Grid x:Name="Container" Padding="30">
  <Button Content="Save"
    Click="OnSave"
    KeyboardAcceleratorPlacementMode="Auto"
    KeyboardAcceleratorPlacementTarget="{x:Bind Container}">
    <Button.KeyboardAccelerators>
      <KeyboardAccelerator  Key="S" Modifiers="Control" />
    </Button.KeyboardAccelerators>
  </Button>
</Grid>

Rótulos

Em alguns casos, recomendamos usar o rótulo de um controle para identificar se o controle tem um acelerador de teclado associado e, em caso afirmativo, qual é a combinação de teclas do acelerador.

Alguns controles de plataforma fazem isso por padrão, especificamente os objetos MenuFlyoutItem e ToggleMenuFlyoutItem, enquanto o AppBarButton e o AppBarToggleButton fazem isso quando aparecem no menu de estouro da CommandBar.

Keyboard accelerators described in a menu item label.
Aceleradores de teclado descritos em um rótulo de item de menu

Você pode substituir o texto do acelerador padrão para o rótulo por meio da propriedade KeyboardAcceleratorTextOverride dos controles MenuFlyoutItem, ToggleMenuFlyoutItem, AppBarButton e AppBarToggleButton (use um único espaço para nenhum texto).

Observação

O texto de substituição não será apresentado se o sistema não puder detectar um teclado conectado (você mesmo pode verificar isso por meio da propriedade KeyboardPresent ).

Conceitos avançados

Aqui, analisamos alguns aspectos de baixo nível dos aceleradores de teclado.

Prioridade do evento de entrada

Os eventos de entrada ocorrem em uma sequência específica que você pode interceptar e manipular com base nos requisitos do seu aplicativo.

O evento de borbulhamento KeyDown/KeyUp

Em XAML, um pressionamento de tecla é processado como se houvesse apenas um pipeline borbulhante de entrada. Esse pipeline de entrada é usado pelos eventos KeyDown/KeyUp e entrada de caracteres. Por exemplo, se um elemento tiver foco e o usuário pressionar uma tecla para baixo, um evento KeyDown será gerado no elemento, seguido pelo pai do elemento e assim por diante na árvore, até o args. A propriedade manipulada é true.

O evento KeyDown também é usado por alguns controles para implementar os aceleradores de controle internos. Quando um controle tem um acelerador de teclado, ele manipula o evento KeyDown, o que significa que não haverá borbulhamento de eventos KeyDown. Por exemplo, o RichEditBox suporta cópia com Ctrl+C. Quando Ctrl é pressionado, o evento KeyDown é acionado e bolhas, mas quando o usuário pressiona C ao mesmo tempo, o evento KeyDown é marcado como Manipulado e não é gerado (a menos que o parâmetro handledEventsToo de UIElement.AddHandler esteja definido como true).

O evento CharacterReceived

Como o evento CharacterReceived é acionado após o evento KeyDown para controles de texto, como TextBox, você pode cancelar a entrada de caracteres no manipulador de eventos KeyDown.

Os eventos PreviewKeyDown e PreviewKeyUp

Os eventos de entrada de visualização são acionados antes de quaisquer outros eventos. Se você não manipular esses eventos, o acelerador do elemento que tem o foco será acionado, seguido pelo evento KeyDown. Ambos os eventos borbulham até serem manipulados.

Diagram showing the key event sequenceSequência de eventos-chave

Ordem dos eventos:

Visualizar eventos KeyDown
...
Acelerador de aplicativos
Método OnKeyDown
Evento KeyDown
Aceleradores de aplicativos no pai
Método OnKeyDown no pai
Evento KeyDown no pai
(Bolhas até a raiz)
...
Evento CharacterReceived
Eventos PreviewKeyUp
KeyUpEvents

Quando o evento accelerator é manipulado, o evento KeyDown também é marcado como manipulado. O evento KeyUp permanece sem manipulação.

Resolvendo aceleradores

Um evento do acelerador de teclado borbulha do elemento que tem foco até a raiz. Se o evento não for manipulado, a estrutura XAML procurará outros aceleradores de aplicativo sem escopo fora do caminho borbulhante.

Quando dois aceleradores de teclado são definidos com a mesma combinação de teclas, o primeiro acelerador de teclado encontrado na árvore visual é chamado.

Os aceleradores de teclado com escopo são chamados somente quando o foco está dentro de um escopo específico. Por exemplo, em uma Grade que contém dezenas de controles, um acelerador de teclado pode ser chamado para um controle somente quando o foco estiver dentro da Grade (o proprietário do escopo).

Aceleradores de escopo programaticamente

O método UIElement.TryInvokeKeyboardAccelerator invoca quaisquer aceleradores correspondentes na subárvore do elemento.

O método UIElement.OnProcessKeyboardAccelerators é executado antes do acelerador de teclado. Esse método passa um objeto ProcessKeyboardAcceleratorArgs que contém a tecla, o modificador e um Boolean indicando se o acelerador de teclado é manipulado. Se marcado como manipulado, o acelerador de teclado borbulha (para que o acelerador de teclado externo nunca seja chamado).

Observação

OnProcessKeyboardAccelerators sempre é acionado, manipulado ou não (semelhante ao evento OnKeyDown). Você deve verificar se o evento foi marcado como manipulado.

Neste exemplo, usamos OnProcessKeyboardAccelerators e TryInvokeKeyboardAccelerator para definir o escopo de aceleradores de teclado para o objeto Page:

protected override void OnProcessKeyboardAccelerators(
  ProcessKeyboardAcceleratorArgs args)
{
  if(args.Handled != true)
  {
    this.TryInvokeKeyboardAccelerator(args);
    args.Handled = true;
  }
}

Localizar os aceleradores

Recomendamos localizar todos os aceleradores de teclado. Você pode fazer isso com o arquivo de recursos padrão (.resw) e o atributo x:Uid em suas declarações XAML. Neste exemplo, o Tempo de Execução do Windows carrega automaticamente os recursos.

Diagram of keyboard accelerator localization with the resources fileLocalização do acelerador de teclado com o arquivo de recursos

<Button x:Uid="myButton" Click="OnSave">
  <Button.KeyboardAccelerators>
    <KeyboardAccelerator x:Uid="myKeyAccelerator" Modifiers="Control"/>
  </Button.KeyboardAccelerators>
</Button>

Observação

Os aceleradores de teclado são implementados como teclas virtuais. Os aceleradores localizados devem ser escolhidos a partir da coleção predefinida de códigos de chave virtual (caso contrário, ocorrerá um erro de analisador XAML).

Configurar um acelerador programaticamente

Aqui está um exemplo de definição programática de um acelerador:

void AddAccelerator(
  VirtualKeyModifiers keyModifiers, 
  VirtualKey key, 
  TypedEventHandler<KeyboardAccelerator, KeyboardAcceleratorInvokedEventArgs> handler )
  {
    var accelerator = 
      new KeyboardAccelerator() 
      { 
        Modifiers = keyModifiers, Key = key
      };
    accelerator.Invoked += handler;
    this.KeyboardAccelerators.Add(accelerator);
  }

Observação

O KeyboardAccelerator não é compartilhável, o mesmo KeyboardAccelerator não pode ser adicionado a vários elementos.

Substituir o comportamento do acelerador de teclado

Você pode manipular o evento KeyboardAccelerator.Invoked para substituir o comportamento padrão do KeyboardAccelerator.

Este exemplo mostra como substituir o comando "Selecionar tudo" (Ctrl+Um acelerador de teclado) em um controle ListView personalizado. Também definimos a propriedade Handled como true para impedir que o evento borbulhe ainda mais.

public class MyListView : ListView
{
  …
  protected override void OnKeyboardAcceleratorInvoked(KeyboardAcceleratorInvokedEventArgs args) 
  {
    if(args.Accelerator.Key == VirtualKey.A 
      && args.Accelerator.Modifiers == KeyboardModifiers.Control)
    {
      CustomSelectAll(TypeOfSelection.OnlyNumbers); 
      args.Handled = true;
    }
  }
  …
}

Exemplos