Aceleradores de teclado

Imagem principal do teclado do Surface

As teclas aceleradoras (ou aceleradores de teclado) são atalhos de teclado que melhoram a usabilidade e a acessibilidade de seus aplicativos 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 determinadas 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, Seta, 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 dá suporte a Ctrl+A para selecionar todos os itens na lista e RichEditBox dá suporte a Ctrl+Tab para inserir um Tab 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 (o uso de rótulos ou padrões estabelecidos pode ajudar com isso).

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

Captura de tela de aceleradores de teclado em um rótulo de item de menu.
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 dê 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 que podem pressionar apenas uma tecla por 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 com 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 de 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 por usar o teclado porque os comandos baseados no teclado podem ser inseridos mais rapidamente e não exigem que eles retirem 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 usados com mais frequência.

Especificar um acelerador de teclado

Use as APIs KeyboardAccelerator para criar aceleradores de teclado em aplicativos do Windows. Com essas APIs, você não precisa lidar com 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 do item de menu ou a dica de ferramenta. Neste exemplo, declaramos aceleradores de teclado apenas 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>

Captura de tela de um acelerador de teclado em uma dica de ferramenta.
Acelerador de teclado descrito em uma dica de ferramenta

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

Observação

Aceleradores de tecla única (A, Delete, F2, Barra de espaço, Esc, Tecla multimídia) e 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 com 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 (Automação da Interface do Usuário) para executar uma ação quando um acelerador é invocado.

O 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 dar suporte ao evento Click (normalmente, um controle é invocado 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 verifica se o controle implementa o padrão de controle Invoke e, em caso afirmativo, o ativa (não é necessário escutar 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 implementar vários padrões de controle, apenas um poderá ser ativado por meio de um acelerador. Os padrões de controle são priorizados da seguinte maneira:

  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. Definir Handled como true no manipulador de eventos suprime essa mensagem.")

Comportamento do acelerador de teclado personalizado

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 evento do acelerador de propagação. O padrão é false.
  • Elemento (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, dão 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 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 invocado 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 aceleradoras de teclado para os usuários. Por padrão, esse é cada modificador (na ordem de enumeração VirtualModifiers) seguido pela chave (e separado por sinais "+"). 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

Definir 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 resultados (ou semelhantes), mas isso nem sempre é possível devido a diferenças na 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
Cole o conteúdo da área de transferência Ctrl + V, Shift + Inserir
Cole 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
Sublinhado Ctrl + U
Itálico Ctrl + I
Navegação
Localizar conteúdo em um controle ou janela focada Ctrl +F
Vá para o próximo resultado da pesquisa F3
Vá para o próximo painel da interface do usuário F6
Vá para o painel de interface anterior Shift + F6
Outras ações
Adicionar favoritos Ctrl + D
Atualizar F5 ou Ctrl + R
Ampliar Ctrl + +
Reduzir Ctrl + -
Zoom para a visualizaçã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 ferramenta

Como os aceleradores de teclado normalmente não são descritos diretamente na interface do usuário do seu aplicativo 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 segura 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, somente o primeiro será apresentado.

Captura de tela de um botão Salvar com uma dica de ferramenta acima dele que indica suporte para o acelerador Ctrl+S.
Combinação de teclas aceleradoras na dica de ferramenta

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

Observação

Especificar 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>

Captura de tela de três botões rotulados como Button1, Button2 e Button3 com uma dica de ferramenta acima de Button2 que indica suporte para o acelerador Windows+B.

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

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

Captura de tela de um botão com um ícone de disco e uma dica de ferramenta que inclui o texto padrão Salvar anexado com o acelerador Ctrl+S entre parênteses.

Combinação de teclas aceleradoras 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>

Captura de tela de um Menu com MenuFlyoutItems que incluem combinações de teclas aceleradoras.
Combinação de teclas aceleradoras acrescentada 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 aceleradoras de teclado para um botão Salvar com o contêiner Grid 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 um rótulo de 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 do CommandBar.

Aceleradores de teclado descritos em um rótulo de item de menu.
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 anexado (você mesmo pode verificar isso por meio da propriedade KeyboardPresent ).

Conceitos avançados

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

Prioridade de 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 de propagação de entrada. Esse pipeline de entrada é usado pelos eventos KeyDown/KeyUp e pela 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é os argumentos. Handled é 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á propagação do evento KeyDown. Por exemplo, o RichEditBox dá suporte à cópia com Ctrl+C. Quando Ctrl é pressionado, o evento KeyDown é acionado e borbulha, 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 seja definido como true).

O evento CharacterReceived

Como o evento CharacterReceived é disparado 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 qualquer outro evento. 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 tratados.

Diagrama mostrando a sequência de eventos chaveSequência de eventos chave

Ordem dos eventos:

Visualizar eventos KeyDown

Acelerador de aplicativos
Método OnKeyDown
Evento KeyDown
Aceleradores de aplicativo no pai
OnKeyDown no pai
KeyDown no pai
(Bolhas até a raiz)

Evento CharacterReceived
Eventos PreviewKeyUp
Eventos KeyUp

Quando o evento acelerador é manipulado, o evento KeyDown também é marcado como manipulado. O evento KeyUp permanece sem tratamento.

Resolvendo aceleradores

Um evento 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 de propagação.

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

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

Aceleradores de escopo programaticamente

O método UIElement.TryInvokeKeyboardAccelerator invoca todos os 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 chave, o modificador e um booliano indicando se o acelerador de teclado é manipulado. Se marcado como manipulado, o acelerador de teclado borbulha (portanto, o acelerador de teclado externo nunca é invocado).

Observação

OnProcessKeyboardAccelerators sempre é acionado, seja 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;
  }
}

Localize 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.

Diagrama de localização do acelerador de teclado com o arquivo de recursosLocalizaçã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 na 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

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" (acelerador de teclado Ctrl+A) em um controle ListView personalizado. Também definimos a propriedade Handled como true para impedir que o evento se espalhe 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;
    }
  }
  …
}

Amostras