Événements de clavier

Événements de clavier et focus

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

Événement 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-là, il peut sembler qu’un événement d’entrée n’a pas lieu car votre écouteur d’événements n’appelle pas le gestionnaire associé. En général, ces touches sont gérées par le gestionnaire de classe pour fournir une prise en charge intégrée de l’accessibilité de base du clavier. Par exemple, la classe Button remplace les événements OnKeyDown pour la touche Espace et la touche Entrée (ainsi que pour OnPointerPressed) et les achemine 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 l’appel du bouton, comme en cas d’appui avec un doigt ou de clic avec une souris. Les touches autres que Espace ou Entrée déclenchent quand même les événements KeyDown et KeyUp. Pour plus d’informations sur le fonctionnement de cette gestion des événements basée sur la classe (en particulier la section Gestionnaires d’événements d’entrée dans les contrôles), voir 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 élément individuel reçoit le focus lorsque l’utilisateur clique ou appuie directement sur cet élément dans l’interface ou qu’il utilise la touche Tab dans la zone de contenu.

Vous pouvez également appeler la méthode Focus d’un contrôle pour forcer le focus. Cette action est nécessaire lorsque vous implémentez des touches de raccourci, car le focus du clavier n’est pas défini par défaut lors du chargement de votre interface utilisateur. Pour plus d’informations, voir Exemple de touches de raccourci, plus loin dans cette rubrique.

Pour qu’un contrôle puisse recevoir le focus d’entrée, il doit être activé, visible et avoir les propriétés IsTabStop et HitTestVisible associées à la valeur 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 être déclenché et répondre aux événements d’entrée de clavier, tel que 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, l’ordre de tabulation des contrôles est celui dans lequel les contrôles apparaissent dans le code XAML (Extensible Application Markup Language). Vous pouvez cependant changer cet ordre à l’aide de la propriété TabIndex. Pour plus d’informations, voir Implémentation de l’accessibilité du clavier.

Gestionnaires d’événements de 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 auquel le gestionnaire d’événements est attaché.
  • Donnée d’événement. Pour les événements de clavier, ces données seront un instance de KeyRoutedEventArgs. Le délégué des gestionnaires est KeyEventHandler. Les propriétés les plus significatives de KeyRoutedEventArgs pour la plupart des scénarios de gestionnaires sont Key et éventuellement KeyStatus.
  • OriginalSource. Les événements de clavier étant des événements routés, les données d’événements fournissent OriginalSource. Si vous autorisez délibérément des événements à être proposés par le biais d’un arbre d’objets, OriginalSource est parfois l’objet de la question plutôt que l’expéditeur, bien que cela dépende de la conception de votre application. Pour plus d’informations concernant l’utilisation de OriginalSource à la place de l’expéditeur, voir la section Événements routés de clavier de cette rubrique ou Vue d’ensemble des événements et des événements routés.

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

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

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

Vous pouvez également associer un gestionnaire d’événements à du 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 incomplète du gestionnaire d’événements KeyUp qui a été 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 de clavier utilisent KeyRoutedEventArgs pour les données d’événements, 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. Vous êtes généralement à l’écoute des événements en vue de traiter une valeur de touche spécifique. Afin de déterminer quelle touche est enfoncée ou relâchée, vérifiez la valeur Key dans les données d’événements. Key renvoie une valeur VirtualKey. L’énumération VirtualKey inclut toutes les touches prises en charge.

Touches de modification

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

Notes

Pour connaître les raccourcis clavier intégrés, consultez Touches d’accès et Raccourcis 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 case activée si une touche de modification est à l’état enfoncé.

Vous pouvez également utiliser la fonction GetKeyState() de CoreWindow (obtenue par le biais de CoreWindow.GetForCurrentThread()) pour case activée 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 du code stub pour la première implémentation.

Notes

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 du contenu multimédia à l’aide des boutons Lecture, Pause et Arrêt ou des raccourcis clavier Ctrl+P, Ctrl+A et Ctrl+S. Le bouton XAML affiche les raccourcis à l’aide des info-bulles et des propriétés AutomationProperties dans les étiquettes de bouton. Cette documentation d’auto-apprentissage est importante afin d’augmenter la facilité d’utilisation et l’accessibilité de votre application. Pour plus d’informations, voir Accessibilité du clavier.

Notez également que la page définit le focus d’entrée sur elle-même lors de son chargement. Sans cette étape, aucun contrôle n’a le focus d’entrée initial et l’application ne déclenche pas les événements d’entrée tant qu’un utilisateur n’a pas défini le focus d’entrée manuellement (par exemple en utilisant la touche de tabulation 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

Notes

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

La définition d’AutomationProperties.AcceleratorKey ou d’AutomationProperties.AccessKey ne constitue pas une action proprement dite. Vous devrez quand même associer des gestionnaires pour les événements KeyDown ou KeyUp afin de mettre réellement en œuvre le comportement de la touche de raccourci dans l’application. De même, l’ornement de soulignement du texte n’est pas fourni automatiquement pour une touche d’accès. Vous devez souligner explicitement le texte de la clé spécifique dans votre mnémonique en tant que mise en forme soulignée inline si vous souhaitez afficher le texte souligné dans l’interface utilisateur.

 

Événements routés de clavier

Certains événements sont des événements routés, comme KeyDown et KeyUp. Les événements routés utilisent la stratégie de routage de propagation. La stratégie de routage de propagation signifie qu’un événement provenant d’un objet enfant est ensuite routé jusqu’aux objets parents successifs dans l’arbre d’objets, ce qui offre ainsi une autre opportunité de gérer le même événement et d’interagir avec les mêmes données d’événements.

Considérez l’exemple de code XAML suivant, dans lequel des événements KeyUp sont définis pour un objet Canvas et deux objets Button. Dans ce cas, si vous relâchez une touche tandis que le focus est détenu par l’un des objets Button, l’événement KeyUp est déclenché. L’événement est ensuite propagé à l’objet Canvas 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. Dans ce cas, OriginalSource signale l’objet qui a déclenché l’événement. L’objet ne pouvait pas être l’objet StackPanel, car StackPanel n’est pas un contrôle et il ne peut pas avoir le focus. Seul un des deux boutons au sein de l’objet StackPanel a pu déclencher l’événement, mais lequel ? Vous utilisez OriginalSource pour identifier l’objet source de l’événement réel si vous gérez l’événement sur un objet parent.

Propriété Handled dans des données d’événements

En fonction de votre stratégie de gestion des événements, il se peut que vous vouliez qu’un seul gestionnaire d’événements réagisse à un événement de propagation. Ainsi, tout gestionnaire KeyUp spécifique attaché à l’un des contrôles Button a en premier lieu la possibilité de gérer cet événement. Dans ce cas, il se peut que vous ne vouliez 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.

Le rôle de la propriété Handled dans une classe de données d’événements routés est de signaler qu’un autre gestionnaire que vous aviez enregistré précédemment sur l’itinéraire des événements a déjà agi. Cela influence le comportement du système d’événements routés. Lorsque vous définissez la valeur de la propriété 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 associer des gestionnaires pouvant agir sur des événements déjà marqués comme étant 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 propre au langage pour ajouter des gestionnaires, comme += en C#.

L’une des limitations générales de cette technique est le fait que l’API AddHandler utilise un paramètre de type RoutedEvent qui identifie l’événement routé en question. Tous les événements routés ne fournissent pas un identificateur RoutedEvent et cette considération affecte par conséquent les événements routés qui peuvent encore être gérés dans le cas Handled. Les événements KeyDown et KeyUp ont des identificateurs d’événements routés (KeyDownEvent et KeyUpEvent) sur UIElement. Toutefois, les autres événements tels que TextBox.TextChanged ne possèdent pas d’identificateurs d’événements routés. Par conséquent, ils ne peuvent pas être utilisés pour la technique AddHandler.

Remplacement des événements et du comportement du clavier

Vous pouvez remplacer les événements de touche pour certains contrôles spécifiques (tels que GridView) pour garantir une navigation cohérente pour différents périphériques de saisie, notamment le clavier et le boîtier de commande.

Dans l’exemple suivant, nous sousclassons le contrôle et nous substituons le comportement KeyDown pour déplacer le focus sur 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);
    }
  }

Notes

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

Commandes

Un petit nombre d’éléments d’interface utilisateur fournit la prise en charge intégrée pour les commandes. Les commandes utilisent les événements routés associés à une entrée dans leur implémentation sous-jacente et permettent de traiter l’entrée d’interface utilisateur associée (une certaine action du pointeur, une touche d’accès rapide spécifique), en invoquant un seul gestionnaire de commandes.

Si les commandes sont disponibles pour un élément d’interface utilisateur, envisagez d’utiliser ses API de commandes plutôt que les événements d’entrée discrets. Pour plus d’informations, voir ButtonBase.Command.

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

Entrée de texte et contrôles

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

En règle générale, 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, comme prévu de par sa conception, il se peut qu’un contrôle ne réponde pas à l’ensemble des valeurs de touches qui lui sont envoyées par le biais des événements de touches. Le comportement est spécifique à chaque contrôle.

En guise d’exemple, ButtonBase (la classe de base pour Button) traite l’élément KeyUp de sorte qu’il puisse surveiller la barre d’espace ou la touche Entrée. ButtonBase considère que KeyUp équivaut à un clic de bouton gauche de souris pour les besoins du déclenchement d’événement Click. Ce traitement de l’événement s’effectue lorsque ButtonBase remplace la méthode virtuelle OnKeyUp. Dans son implémentation, la valeur true est affectée à Handled. Le résultat est que tout parent d’un bouton à l’écoute d’un événement de touche, dans le cas de la barre d’espace, ne recevra pas l’événement déjà géré pour ses propres gestionnaires.

Un autre exemple est TextBox. Certaines clés, 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 de contrôle. L’élément TextBox marque ces cas d’événements 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 accélérateur spécifiques ou présente un comportement de contrôle ou de focus qui est similaire au scénario décrit pour TextBox, vous devez placer cette logique dans vos propres remplacements OnKeyDown / OnKeyUp.

Le clavier tactile

Les contrôles de saisie de texte fournissent le support automatique du clavier tactile. Lorsque l’utilisateur définit le focus d’entrée sur un contrôle de texte à l’aide de l’entrée tactile, le clavier tactile apparaît automatiquement. Lorsque le focus d’entrée n’est pas placé sur un contrôle de texte, le clavier tactile est masqué.

Lorsque le clavier tactile apparaît, votre interface utilisateur est automatiquement repositionnée afin que l’élément ciblé reste visible. Des zones importantes de l’interface utilisateur peuvent alors sortir de l’écran. Vous pouvez désactiver ce comportement par défaut et effectuer vos propres ajustements de l’interface utilisateur lorsque le clavier tactile apparaît. Pour plus d’informations, consultez l’exemple clavier tactile.

Si vous créez un contrôle personnalisé qui nécessite une saisie de texte mais ne découle pas d’un contrôle de saisie 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 clavier tactile.

Les touches appuyant sur le clavier tactile déclenchent les événements KeyDown et KeyUp , tout comme les appuis sur les claviers matériels. Cependant, le clavier tactile ne déclenche pas d’événements de saisie pour les touches Ctrl+A, Ctrl+Z, Ctrl+X, Ctrl+C et Ctrl+V, qui sont réservées à la manipulation de texte dans le contrôle de saisie.

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 des entrées fournit une indication sur le 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 entrer un code confidentiel à 4 chiffres, définissez la propriété InputScope sur Number. Cela indique au système qu’il doit afficher la disposition du pavé numérique, ce qui facilite l’entrée d’un PIN par l’utilisateur. Pour plus d’informations, voir Comment utiliser l’étendue des entrées pour modifier le clavier tactile.

Développeurs

Concepteurs

Exemples

Exemples d’archive