Partage via


Événements de clavier

Événements de clavier et focus

Les événements de clavier suivants peuvent se produire pour le matériel et les claviers tactiles.

Event Description
KeyDown Se produit lors de la pression sur une touche.
KeyUp Se produit lors du relâchement d'une touche.

Important

Certains contrôles XAML gèrent les événements d’entrée en interne. Dans ces cas, il peut apparaître qu’un événement d’entrée ne se produit pas, car votre écouteur d’événements n’appelle pas le gestionnaire associé. En règle générale, ce sous-ensemble de touches est traité par le gestionnaire de classes pour fournir une prise en charge intégrée de l’accessibilité du clavier de base. Par exemple, la classe Button remplace les événements OnKeyDown pour la touche Espace et la touche Entrée (ainsi que SurPointerPressed) et les route vers l’événement Click du contrôle. Lorsqu’une touche est gérée par la classe de contrôle, les événements KeyDown et KeyUp ne sont pas déclenchés.
Cela fournit un équivalent de clavier intégré pour appeler le bouton, similaire à son appui avec un doigt ou en cliquant dessus avec une souris. Les clés autres que l’espace ou Entrée déclenchent toujours les événements KeyDown et KeyUp. Pour plus d’informations sur le fonctionnement de la gestion basée sur les classes des événements (plus précisément, la section « Gestionnaires d’événements d’entrée dans les contrôles »), consultez La vue d’ensemble des événements et des événements routés.

Les contrôles de votre interface utilisateur génèrent des événements de clavier uniquement lorsqu’ils ont le focus d’entrée. Un contrôle individuel obtient le focus lorsque l’utilisateur clique ou appuie directement sur ce contrôle dans la disposition, ou utilise la touche Tab pour passer à une séquence d’onglets dans la zone de contenu.

Vous pouvez également appeler la méthode Focus d’un contrôle pour forcer le focus. Cela est nécessaire lorsque vous implémentez des touches de raccourci, car le focus clavier n’est pas défini par défaut lorsque votre interface utilisateur se charge. Pour plus d’informations, consultez l’exemple de touches de raccourci plus loin dans cette rubrique.

Pour qu’un contrôle reçoive le focus d’entrée, il doit être activé, visible et avoir des valeurs de propriété IsTabStop et HitTestVisible de true. Il s’agit de l’état par défaut de la plupart des contrôles. Lorsqu’un contrôle a le focus d’entrée, il peut déclencher et répondre aux événements d’entrée au clavier, comme décrit plus loin dans cette rubrique. Vous pouvez également répondre à un contrôle qui reçoit ou perd le focus en gérant les événements GotFocus et LostFocus.

Par défaut, la séquence d’onglets des contrôles est l’ordre dans lequel ils apparaissent dans le langage XAML (Extensible Application Markup Language). Toutefois, vous pouvez modifier cet ordre à l’aide de la propriété TabIndex. Pour plus d’informations, consultez Implémentation de l’accessibilité du clavier.

Gestionnaires d’événements clavier

Un gestionnaire d’événements d’entrée implémente un délégué qui fournit les informations suivantes :

  • Expéditeur de l’événement. L’expéditeur signale l’objet où le gestionnaire d’événements est attaché.
  • Donnée d’événement. Pour les événements clavier, ces données seront une instance de KeyRoutedEventArgs. Le délégué pour les gestionnaires est KeyEventHandler. Les propriétés les plus pertinentes de KeyRoutedEventArgs pour la plupart des scénarios de gestionnaire sont Key et éventuellement KeyStatus.
  • OriginalSource. Étant donné que les événements clavier sont routés, les données d’événement fournissent OriginalSource. Si vous autorisez délibérément les événements à monter dans une arborescence d’objets, OriginalSource est parfois l’objet de préoccupation plutôt que l’expéditeur. Toutefois, cela dépend de votre conception. Pour plus d’informations sur la façon dont vous pouvez utiliser OriginalSource plutôt que l’expéditeur, consultez la section « Événements routés au clavier » de cette rubrique, ou Événements et vue d’ensemble des événements routés.

Attachement d’un gestionnaire d’événements de clavier

Vous pouvez attacher des fonctions de gestionnaire d’événements clavier pour n’importe quel objet qui inclut l’événement en tant que membre. Cela inclut n’importe quelle classe dérivée UIElement. L’exemple XAML suivant montre comment attacher des gestionnaires pour l’événement KeyUp pour une grille.

<Grid KeyUp="Grid_KeyUp">
  ...
</Grid>

Vous pouvez également attacher un gestionnaire d’événements dans le code. Pour plus d’informations, consultez Vue d’ensemble des événements et des événements routés.

Définition d’un gestionnaire d’événements de clavier

L’exemple suivant montre la définition du gestionnaire d’événements incomplet pour le gestionnaire d’événements KeyUp attaché dans l’exemple précédent.

void Grid_KeyUp(object sender, KeyRoutedEventArgs e)
{
    //handling code here
}
Private Sub Grid_KeyUp(ByVal sender As Object, ByVal e As KeyRoutedEventArgs)
    ' handling code here
End Sub
void MyProject::MainPage::Grid_KeyUp(
  Platform::Object^ sender,
  Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
  {
      //handling code here
  }

Utilisation de KeyRoutedEventArgs

Tous les événements clavier utilisent KeyRoutedEventArgs pour les données d’événement, et KeyRoutedEventArgs contient les propriétés suivantes :

Clés virtuelles

L’événement KeyDown est déclenché si une touche est enfoncée. De même, KeyUp est déclenché si une clé est libérée. En règle générale, vous écoutez les événements pour traiter une valeur de clé spécifique. Pour déterminer la touche enfoncée ou libérée, vérifiez la valeur de la clé dans les données d’événement. La clé retourne une valeur VirtualKey. L’énumération VirtualKey inclut toutes les clés prises en charge.

Touches de modification

Les touches de modification sont des touches telles que Ctrl ou Maj que les utilisateurs appuient généralement en combinaison avec d’autres touches. Votre application peut utiliser ces combinaisons comme raccourcis clavier personnalisés pour appeler des commandes d’application.

Remarque

Pour connaître les raccourcis clavier intégrés, consultez touches d’accès et accélérateurs clavier.

Vous pouvez détecter les combinaisons de touches de raccourci dans les gestionnaires d’événements KeyDown et KeyUp. Lorsqu’un événement de clavier se produit pour une touche non modificateur, vous pouvez ensuite vérifier si une touche de modificateur est dans l’état appuyé.

Vous pouvez également utiliser la fonction GetKeyState() de CoreWindow (obtenue via CoreWindow.GetForCurrentThread()) pour vérifier l’état du modificateur lorsqu’une touche non modificateur est enfoncée.

Les exemples suivants implémentent cette deuxième méthode tout en incluant le code stub pour la première implémentation.

Remarque

La touche Alt est représentée par la valeur VirtualKey.Menu .

Exemple de touches de raccourci

L’exemple suivant montre comment implémenter un ensemble de touches de raccourci personnalisées. Dans cet exemple, les utilisateurs peuvent contrôler la lecture multimédia à l’aide des boutons Lecture, Pause et Arrêt ou Ctrl+P, Ctrl+A et Ctrl+S raccourcis clavier. Le code XAML du bouton affiche les raccourcis à l’aide d’info-bulles et de propriétés AutomationProperties dans les étiquettes de bouton. Cette auto-documentation est importante pour augmenter la facilité d’utilisation et l’accessibilité de votre application. Pour plus d’informations, consultez l’accessibilité du clavier.

Notez également que la page définit le focus d’entrée sur lui-même lorsqu’il est chargé. Sans cette étape, aucun contrôle n’a le focus d’entrée initial et l’application ne déclenche pas d’événements d’entrée tant que l’utilisateur n’a pas défini manuellement le focus d’entrée (par exemple, en tablant ou en cliquant sur un contrôle).

<Grid KeyDown="Grid_KeyDown">

  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

  <MediaElement x:Name="DemoMovie" Source="xbox.wmv"
    Width="500" Height="500" Margin="20" HorizontalAlignment="Center" />

  <StackPanel Grid.Row="1" Margin="10"
    Orientation="Horizontal" HorizontalAlignment="Center">

    <Button x:Name="PlayButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+P"
      AutomationProperties.AcceleratorKey="Control P">
      <TextBlock>Play</TextBlock>
    </Button>

    <Button x:Name="PauseButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+A"
      AutomationProperties.AcceleratorKey="Control A">
      <TextBlock>Pause</TextBlock>
    </Button>

    <Button x:Name="StopButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+S"
      AutomationProperties.AcceleratorKey="Control S">
      <TextBlock>Stop</TextBlock>
    </Button>

  </StackPanel>

</Grid>
//showing implementations but not header definitions
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
    (void) e;    // Unused parameter
    this->Loaded+=ref new RoutedEventHandler(this,&amp;MainPage::ProgrammaticFocus);
}
void MainPage::ProgrammaticFocus(Object^ sender, RoutedEventArgs^ e) 
{
    this->Focus(Windows::UI::Xaml::FocusState::Programmatic);
}

void KeyboardSupport::MainPage::MediaButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
    FrameworkElement^ fe = safe_cast<FrameworkElement^>(sender);
    if (fe->Name == "PlayButton") {DemoMovie->Play();}
    if (fe->Name == "PauseButton") {DemoMovie->Pause();}
    if (fe->Name == "StopButton") {DemoMovie->Stop();}
}


bool KeyboardSupport::MainPage::IsCtrlKeyPressed()
{
    auto ctrlState = CoreWindow::GetForCurrentThread()->GetKeyState(VirtualKey::Control);
    return (ctrlState & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down;
}

void KeyboardSupport::MainPage::Grid_KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
{
    if (e->Key == VirtualKey::Control) isCtrlKeyPressed = true;
}


void KeyboardSupport::MainPage::Grid_KeyUp(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
{
    if (IsCtrlKeyPressed()) 
    {
        if (e->Key==VirtualKey::P) { DemoMovie->Play(); }
        if (e->Key==VirtualKey::A) { DemoMovie->Pause(); }
        if (e->Key==VirtualKey::S) { DemoMovie->Stop(); }
    }
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    // Set the input focus to ensure that keyboard events are raised.
    this.Loaded += delegate { this.Focus(FocusState.Programmatic); };
}

private void MediaButton_Click(object sender, RoutedEventArgs e)
{
    switch ((sender as Button).Name)
    {
        case "PlayButton": DemoMovie.Play(); break;
        case "PauseButton": DemoMovie.Pause(); break;
        case "StopButton": DemoMovie.Stop(); break;
    }
}

private static bool IsCtrlKeyPressed()
{
    var ctrlState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);
    return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
}

private void Grid_KeyDown(object sender, KeyRoutedEventArgs e)
{
    if (IsCtrlKeyPressed())
    {
        switch (e.Key)
        {
            case VirtualKey.P: DemoMovie.Play(); break;
            case VirtualKey.A: DemoMovie.Pause(); break;
            case VirtualKey.S: DemoMovie.Stop(); break;
        }
    }
}
Private isCtrlKeyPressed As Boolean
Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)

End Sub

Private Function IsCtrlKeyPressed As Boolean
    Dim ctrlState As CoreVirtualKeyStates = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);
    Return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
End Function

Private Sub Grid_KeyDown(sender As Object, e As KeyRoutedEventArgs)
    If IsCtrlKeyPressed() Then
        Select Case e.Key
            Case Windows.System.VirtualKey.P
                DemoMovie.Play()
            Case Windows.System.VirtualKey.A
                DemoMovie.Pause()
            Case Windows.System.VirtualKey.S
                DemoMovie.Stop()
        End Select
    End If
End Sub

Private Sub MediaButton_Click(sender As Object, e As RoutedEventArgs)
    Dim fe As FrameworkElement = CType(sender, FrameworkElement)
    Select Case fe.Name
        Case "PlayButton"
            DemoMovie.Play()
        Case "PauseButton"
            DemoMovie.Pause()
        Case "StopButton"
            DemoMovie.Stop()
    End Select
End Sub

Remarque

La définition d’AutomationProperties.AcceleratorKey ou AutomationProperties.AccessKey en XAML fournit des informations de chaîne, qui documentent la touche de raccourci pour appeler cette action particulière. Les informations sont capturées par les clients Microsoft UI Automation tels que le Narrateur et sont généralement fournies directement à l’utilisateur.

La définition d’AutomationProperties.AcceleratorKey ou AutomationProperties.AccessKey n’a aucune action propre. Vous devrez toujours joindre des gestionnaires pour les événements KeyDown ou KeyUp afin d’implémenter réellement le comportement du raccourci clavier dans votre application. En outre, la décoration de texte souligné pour une clé d’accès n’est pas fournie automatiquement. Vous devez souligner explicitement le texte de la clé spécifique dans votre mise en forme de soulignement inline si vous souhaitez afficher le texte souligné dans l’interface utilisateur.

 

Événements routés au clavier

Certains événements sont routés, notamment KeyDown et KeyUp. Les événements routés utilisent la stratégie de routage de bubbling. La stratégie de routage de basculement signifie qu’un événement provient d’un objet enfant et est ensuite routé vers des objets parents successifs dans l’arborescence d’objets. Cela offre une autre opportunité de gérer le même événement et d’interagir avec les mêmes données d’événement.

Considérez l’exemple XAML suivant, qui gère les événements KeyUp pour un canevas et deux objets Button. Dans ce cas, si vous relâchez une clé pendant que le focus est conservé par l’un des objets Button , il déclenche l’événement KeyUp . L’événement est ensuite en bulle jusqu’au canevas parent.

<StackPanel KeyUp="StackPanel_KeyUp">
  <Button Name="ButtonA" Content="Button A"/>
  <Button Name="ButtonB" Content="Button B"/>
  <TextBlock Name="statusTextBlock"/>
</StackPanel>

L’exemple suivant montre comment implémenter le gestionnaire d’événements KeyUp pour le contenu XAML correspondant dans l’exemple précédent.

void StackPanel_KeyUp(object sender, KeyRoutedEventArgs e)
{
    statusTextBlock.Text = String.Format(
        "The key {0} was pressed while focus was on {1}",
        e.Key.ToString(), (e.OriginalSource as FrameworkElement).Name);
}

Notez l’utilisation de la propriété OriginalSource dans le gestionnaire précédent. Ici, OriginalSource signale l’objet qui a déclenché l’événement. L’objet n’a pas pu être StackPanel, car StackPanel n’est pas un contrôle et ne peut pas avoir le focus. Un seul des deux boutons du StackPanel pourrait avoir déclenché l’événement, mais lequel ? Vous utilisez OriginalSource pour distinguer l’objet source d’événement réel, si vous gérez l’événement sur un objet parent.

Propriété Handled dans les données d’événement

Selon votre stratégie de gestion des événements, vous ne souhaiterez peut-être qu’un seul gestionnaire d’événements à réagir à un événement de bubbling. Par exemple, si vous avez un gestionnaire KeyUp spécifique attaché à l’un des contrôles Button, il aurait la première possibilité de gérer cet événement. Dans ce cas, vous ne souhaiterez peut-être pas que le panneau parent gère également l’événement. Pour ce scénario, vous pouvez utiliser la propriété Handled dans les données d’événement.

L’objectif de la propriété Handled dans une classe de données d’événement routée est de signaler qu’un autre gestionnaire que vous avez inscrit précédemment sur l’itinéraire d’événements a déjà agi. Cela influence le comportement du système d’événements routé. Lorsque vous définissez Handled sur true dans un gestionnaire d’événements, cet événement arrête le routage et n’est pas envoyé aux éléments parents successifs.

AddHandler et événements de clavier déjà gérés

Vous pouvez utiliser une technique spéciale pour attacher des gestionnaires qui peuvent agir sur les événements que vous avez déjà marqués comme gérés. Cette technique utilise la méthode AddHandler pour inscrire un gestionnaire, plutôt que d’utiliser des attributs XAML ou une syntaxe spécifique au langage pour ajouter des gestionnaires, tels que += en C#.

Une limitation générale de cette technique est que l’API AddHandler prend un paramètre de type RoutedEvent identifiant l’événement routé en question. Tous les événements routés ne fournissent pas d’identificateur RoutedEvent, et cette considération affecte donc les événements routés qui peuvent toujours être gérés dans le cas géré. Les événements KeyDown et KeyUp ont des identificateurs d’événement routés (KeyDownEvent et KeyUpEvent) sur UIElement. Toutefois, d’autres événements tels que TextBox.TextChanged n’ont pas d’identificateurs d’événement routés et ne peuvent donc pas être utilisés avec la technique AddHandler.

Substitution des événements et du comportement du clavier

Vous pouvez remplacer les événements clés pour des contrôles spécifiques (tels que GridView) afin de fournir une navigation de focus cohérente pour différents appareils d’entrée, notamment le clavier et le boîtier de commande.

Dans l’exemple suivant, nous subclassons le contrôle et substituons le comportement KeyDown pour déplacer le focus vers le contenu GridView quand une touche de direction est enfoncée.

  public class CustomGridView : GridView
  {
    protected override void OnKeyDown(KeyRoutedEventArgs e)
    {
      // Override arrow key behaviors.
      if (e.Key != Windows.System.VirtualKey.Left && e.Key !=
        Windows.System.VirtualKey.Right && e.Key !=
          Windows.System.VirtualKey.Down && e.Key !=
            Windows.System.VirtualKey.Up)
              base.OnKeyDown(e);
      else
        FocusManager.TryMoveFocus(FocusNavigationDirection.Down);
    }
  }

Remarque

Si vous utilisez un GridView uniquement pour la disposition, envisagez d’utiliser d’autres contrôles tels que ItemsControl avec ItemsWrapGrid.

Commandes

Un petit nombre d’éléments d’interface utilisateur prennent en charge la prise en charge intégrée des commandes. La commande utilise des événements routés liés à l’entrée dans son implémentation sous-jacente. Il permet le traitement des entrées d’interface utilisateur associées, telles qu’une action de pointeur ou une touche d’accélérateur spécifique, en appelant un seul gestionnaire de commandes.

Si la commande est disponible pour un élément d’IU, envisagez d’utiliser ses API de commande au lieu d’événements d’entrée discrets. Pour plus d’informations, consultez ButtonBase.Command.

Vous pouvez également implémenter ICommand pour encapsuler les fonctionnalités de commande que vous appelez à partir de gestionnaires d’événements ordinaires. Cela vous permet d’utiliser la commande même s’il n’existe aucune propriété Command disponible.

Entrée de texte et contrôles

Certains contrôles réagissent aux événements clavier avec leur propre gestion. Par exemple, TextBox est un contrôle conçu pour capturer, puis représenter visuellement du texte entré à l’aide du clavier. Il utilise KeyUp et KeyDown dans sa propre logique pour capturer les séquences de touches, puis déclenche également son propre événement TextChanged si le texte a réellement changé.

Vous pouvez toujours ajouter des gestionnaires pour KeyUp et KeyDown à une zone de texte ou tout contrôle associé destiné à traiter l’entrée de texte. Toutefois, dans le cadre de sa conception prévue, un contrôle peut ne pas répondre à toutes les valeurs clés qui lui sont dirigées par le biais d’événements clés. Le comportement est spécifique à chaque contrôle.

Par exemple, ButtonBase (la classe de base pour Button) traite KeyUp afin qu’il puisse vérifier la barre d’espace ou la touche Entrée. ButtonBase considère KeyUp équivalent à un bouton gauche de la souris vers le bas à des fins de déclenchement d’un événement Click. Ce traitement de l’événement est effectué lorsque ButtonBase remplace la méthode virtuelle OnKeyUp. Dans son implémentation, il définit Handled sur true. Le résultat est que tout parent d’un bouton qui écoute un événement clé, dans le cas d’une barre d’espace, ne reçoit pas l’événement déjà géré pour ses propres gestionnaires.

Un autre exemple est TextBox. Certaines touches, telles que les touches de direction, ne sont pas considérées comme du texte par TextBox et sont plutôt considérées comme spécifiques au comportement de l’interface utilisateur du contrôle. TextBox marque ces cas d’événement comme gérés.

Les contrôles personnalisés peuvent implémenter leur propre comportement de remplacement similaire pour les événements clés en remplaçant OnKeyDown / OnKeyUp. Si votre contrôle personnalisé traite des touches d’accélérateur spécifiques ou a un comportement de contrôle ou de focus similaire au scénario décrit pour TextBox, vous devez placer cette logique dans vos propres remplacements OnKeyDown / OnKeyUp.

Clavier tactile

Les contrôles d’entrée de texte prennent automatiquement en charge le clavier tactile. Lorsque l’utilisateur définit le focus d’entrée sur un contrôle de texte à l’aide d’une entrée tactile, le clavier tactile s’affiche automatiquement. Lorsque le focus d’entrée n’est pas sur un contrôle de texte, le clavier tactile est masqué.

Lorsque le clavier tactile s’affiche, il repositionne automatiquement votre interface utilisateur pour vous assurer que l’élément prioritaire reste visible. Cela peut entraîner le déplacement d’autres zones importantes de votre interface utilisateur. Toutefois, vous pouvez désactiver le comportement par défaut et effectuer vos propres ajustements d’interface utilisateur lorsque le clavier tactile s’affiche. Pour plus d’informations, consultez l’exemple de clavier tactile.

Si vous créez un contrôle personnalisé qui nécessite une entrée de texte, mais ne dérive pas d’un contrôle d’entrée de texte standard, vous pouvez ajouter la prise en charge du clavier tactile en implémentant les modèles de contrôle UI Automation appropriés. Pour plus d’informations, consultez l’exemple de clavier tactile.

Les touches appuient sur le clavier tactile pour déclencher les événements KeyDown et KeyUp, tout comme les touches appuyant sur les claviers matériels. Toutefois, le clavier tactile ne déclenche pas d’événements d’entrée pour Ctrl+A, Ctrl+Z, Ctrl+X, Ctrl+C et Ctrl+V, qui sont réservés pour la manipulation de texte dans le contrôle d’entrée.

Vous pouvez grandement faciliter et accélérer la saisie de données par les utilisateurs dans votre application, en définissant l’étendue des entrées du contrôle de texte afin qu’elle corresponde au type de données attendu de la part de l’utilisateur. L’étendue d’entrée fournit un indicateur du type d’entrée de texte attendu par le contrôle afin que le système puisse fournir une disposition de clavier tactile spécialisée pour le type d’entrée. Par exemple, si une zone de texte est utilisée uniquement pour la saisie d’un code PIN à 4 chiffres, définissez la propriété InputScope sur Number. Cela indique au système d’afficher la disposition numérique du pavé numérique, ce qui facilite l’entrée du code confidentiel par l’utilisateur. Pour plus d’informations, consultez Utiliser l’étendue d’entrée pour modifier le clavier tactile.

Développeurs

Concepteurs

Exemples

Exemples d’archives