Share via


Vue d'ensemble des entrées

Le sous-système Windows Presentation Foundation (WPF) fournit une API puissante pour obtenir des entrées de divers périphériques, y compris la souris, le clavier, le pavé tactile et le stylet. Cette rubrique décrit les services fournis par WPF et explique l'architecture des systèmes d'entrée.

Cette rubrique comprend les sections suivantes.

  • API d'entrée
  • Routage d'événement
  • Gestion des événements d'entrée
  • Entrée de texte
  • Fonctions tactiles et manipulation
  • Focus
  • Position de la souris
  • Capture de la souris
  • Commandes
  • Le système d'entrée et les éléments de base
  • Quoi d'autre ?
  • Rubriques connexes

API d'entrée

L'exposition API d'entrée principale se trouve dans les classes d'élément de base : UIElement, ContentElement, FrameworkElement et FrameworkContentElement. Pour plus d'informations sur les éléments de base, consultez Vue d'ensemble des éléments de base. Ces classes fournissent la fonctionnalité des événements d'entrée associés aux pressions des touches, aux boutons de la souris, à la molette de la souris, aux déplacements de la souris, à la gestion du focus et à la capture de la souris, pour n'en nommer que quelques-uns. En plaçant l'API d'entrée dans les éléments de base au lieu de traiter tous les événements d'entrée comme un service, l'architecture d'entrée permet d'alimenter les événements d'entrée via un objet particulier dans l'interface utilisateur et de prendre en charge un schéma de routage d'événements qui permet à plusieurs éléments de gérer un événement d'entrée. Un grand nombre d'événements sont associés à une paire d'événements. Par exemple, l'événement de relâchement de touche est associé aux événements KeyDown et PreviewKeyDown. La différence dans ces événements réside dans leur routage vers l'élément cible. Les événements d'aperçu parcourent l'arborescence d'éléments de l'élément racine vers l'élément cible. Les événements de propagation se propagent de l'élément cible vers l'élément racine. Le routage d'événement dans WPF est expliqué en détail plus loin dans cette présentation générale et dans Vue d'ensemble des événements routés.

Classes de clavier et de souris

Outre l'API d'entrée dans les classes d'élément de base, les classes Keyboard et Mouse fournissent des API supplémentaires pour utiliser les entrées du clavier et de la souris.

Des exemples d'API d'entrée dans la classe Keyboard sont la propriété Modifiers qui retourne les ModifierKeys utilisées et la méthode IsKeyDown qui détermine si une touche clé spécifique est utilisée.

L'exemple suivant utilise la méthode GetKeyStates pour déterminer si l'utilisateur appuie sur une Key.

            ' Uses the Keyboard.GetKeyStates to determine if a key is down.
            ' A bitwise AND operation is used in the comparison. 
            ' e is an instance of KeyEventArgs.
            If (Keyboard.GetKeyStates(Key.Return) And KeyStates.Down) > 0 Then
                btnNone.Background = Brushes.Red
// Uses the Keyboard.GetKeyStates to determine if a key is down.
// A bitwise AND operation is used in the comparison. 
// e is an instance of KeyEventArgs.
if ((Keyboard.GetKeyStates(Key.Return) & KeyStates.Down) > 0)
{
    btnNone.Background = Brushes.Red;
}

Des exemples d'API d'entrée sur la classe Mouse sont le MiddleButton qui obtient l'état du bouton central de la souris et DirectlyOver qui obtient l'élément sur lequel se trouve le pointeur de la souris.

L'exemple suivant détermine si le LeftButton de la souris a l'état Pressed.

            If Mouse.LeftButton = MouseButtonState.Pressed Then
                UpdateSampleResults("Left Button Pressed")
            End If
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
    UpdateSampleResults("Left Button Pressed");
}

Les classes Mouse et Keyboard sont couvertes en détail dans cette présentation.

Entrée du stylet

WPF a intégré le support du Stylus. Le Stylus est une saisie effectuée à l'aide du stylet déjà utilisée avec Tablet PC. Les applications WPF peuvent traiter le stylet comme une souris en utilisant l'API de la souris, mais WPF expose également une abstraction d'un périphérique stylet qui utilise un modèle semblable au clavier et à la souris. Toutes les APIs de stylet contiennent le mot "Stylus".

Étant donné que le stylet peut faire office de souris, les applications qui prennent uniquement en charge la souris peuvent toujours bénéficier d'un support de stylet automatiquement. Lorsque le stylet est utilisé de cette manière, l'application peut gérer l'événement de stylet approprié et l'événement de souris correspondant. De plus, des services de niveau supérieur, tels que l'entrée d'encre, sont également disponibles via l'abstraction du stylet. Pour plus d'informations sur l'encre comme entrée, consultez Débuter avec l'encre.

Routage d'événement

Un FrameworkElement peut contenir d'autres éléments comme éléments enfants dans son modèle de contenu pour former une arborescence d'éléments. Dans WPF, l'élément parent peut participer à l'entrée envoyée à ses éléments enfants ou d'autres descendants en gérant les événements. Cela est particulièrement utile pour générer des contrôles à partir de contrôles, un processus appelé "composition de contrôle" ou "composition". Pour plus d'informations sur les arborescences d'éléments et sur la manière dont les arborescences d'éléments sont associées aux routes d'événement, consultez Arborescences dans WPF.

Le routage d'événement est le processus d'envoi d'événements à des éléments pour qu'un objet ou un élément dans la route puisse fournir une réponse significative (via la gestion) à un événement dont la source peut correspondre à un élément différent. Les événements routés utilisent l'un de trois mécanismes de routage : routage direct, routage de propagation et tunneling. Dans le routage direct, l'élément source est le seul élément notifié, et l'événement n'est pas routé vers les autres éléments. Toutefois, l'événement routé directement offre des fonctions supplémentaires qui sont uniquement présentes pour les événements routés, par opposition aux événements CLR standard. La propagation remonte l'arborescence d'éléments en notifiant en premier l'élément qui a alimenté l'événement, puis l'élément parent, et ainsi de suite. Le tunneling démarre à la racine de l'arborescence d'éléments et la descend en s'arrêtant au niveau de l'élément source d'origine. Pour plus d'informations sur les événements routés, consultez Vue d'ensemble des événements routés.

Les événements d'entrée WPF forment généralement des paires constituées d'un événement de tunneling et d'un événement de propagation. Les événements de tunneling se distinguent des événements de propagation par le préfixe "Preview". Par exemple, PreviewMouseMove est la version de tunneling d'un événement de déplacement de la souris, et MouseMove est la version de propagation de cet événement. Cet appariement d'événement est une convention qui est implémentée au niveau de l'élément niveau et il ne correspond pas à une fonction inhérente du système d'événements WPF. Pour plus d'informations, consultez la section des événements d'entrée WPF dans Vue d'ensemble des événements routés.

Gestion des événements d'entrée

Pour recevoir l'entrée dans un élément, un gestionnaire d'événements doit être associé à l'événement. En XAML cette opération est simple ; vous faites référence au nom de l'événement sous la forme d'un attribut de l'élément qui écoutera cet événement. Ensuite, vous affectez la valeur de l'attribut au nom du gestionnaire d'événements que vous définissez, selon un délégué. Le gestionnaire d'événements doit être écrit dans le code, tel que C#, et il peut être inclus dans un fichier code-behind.

Les événements de clavier se produisent lorsque le système d'exploitation signale des actions de touche qui se produisent lorsque le focus clavier est sur un élément. Les événements de souris et de stylet entrent dans deux catégories : les événements qui signalent le changement de position du pointeur par rapport à l'élément, et les événements qui signalent le changement d'état des boutons du périphérique.

Exemple d'événement d'entrée de clavier

L'exemple suivant permet d'écouter l'utilisation de la touche de direction Gauche du clavier. Un StackPanel ayant un Button est créé. Un gestionnaire d'événements pour écouter l'utilisation de la touche de direction Gauche est attaché à l'instance Button.

La première section de l'exemple crée le StackPanel et le Button et lie le gestionnaire d'événements de KeyDown.

<StackPanel>
  <Button Background="AliceBlue"
          KeyDown="OnButtonKeyDown"
          Content="Button1"/>
</StackPanel>
            ' Create the UI elements.
            Dim keyboardStackPanel As New StackPanel()
            Dim keyboardButton1 As New Button()

            ' Set properties on Buttons.
            keyboardButton1.Background = Brushes.AliceBlue
            keyboardButton1.Content = "Button 1"

            ' Attach Buttons to StackPanel.
            keyboardStackPanel.Children.Add(keyboardButton1)

            ' Attach event handler.
            AddHandler keyboardButton1.KeyDown, AddressOf OnButtonKeyDown
// Create the UI elements.
StackPanel keyboardStackPanel = new StackPanel();
Button keyboardButton1 = new Button();

// Set properties on Buttons.
keyboardButton1.Background = Brushes.AliceBlue;
keyboardButton1.Content = "Button 1";

// Attach Buttons to StackPanel.
keyboardStackPanel.Children.Add(keyboardButton1);

// Attach event handler.
keyboardButton1.KeyDown += new KeyEventHandler(OnButtonKeyDown);

La deuxième partie est écrite dans le code et elle définit le gestionnaire d'événements. Lorsque la touche de direction Gauche est utilisée et que le Button a le focus clavier, le gestionnaire s'exécute et la couleur Background du Button change. Si une touche est utilisée et qu'il ne s'agit pas de la touche de direction Gauche, la couleur de début du Background du Button est rétablie.

        Private Sub OnButtonKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
            Dim source As Button = TryCast(e.Source, Button)
            If source IsNot Nothing Then
                If e.Key = Key.Left Then
                    source.Background = Brushes.LemonChiffon
                Else
                    source.Background = Brushes.AliceBlue
                End If
            End If
        End Sub
private void OnButtonKeyDown(object sender, KeyEventArgs e)
{
    Button source = e.Source as Button;
    if (source != null)
    {
        if (e.Key == Key.Left)
        {
            source.Background = Brushes.LemonChiffon;
        }
        else
        {
            source.Background = Brushes.AliceBlue;
        }
    }
}

Exemple d'événement d'entrée de souris

Dans l'exemple suivant, la couleur Background d'un Button change lorsque le pointeur de la souris se trouve sur le Button. La couleur Background est restaurée lorsque la souris quitte le Button.

La première section de l'exemple créé le StackPanel et le contrôle Button et lie les gestionnaires d'événements des événements MouseEnter et MouseLeave au Button..

<StackPanel>
  <Button Background="AliceBlue"
          MouseEnter="OnMouseExampleMouseEnter"
          MouseLeave="OnMosueExampleMouseLeave">Button

  </Button>
</StackPanel>
            ' Create the UI elements.
            Dim mouseMoveStackPanel As New StackPanel()
            Dim mouseMoveButton As New Button()

            ' Set properties on Button.
            mouseMoveButton.Background = Brushes.AliceBlue
            mouseMoveButton.Content = "Button"

            ' Attach Buttons to StackPanel.
            mouseMoveStackPanel.Children.Add(mouseMoveButton)

            ' Attach event handler.
            AddHandler mouseMoveButton.MouseEnter, AddressOf OnMouseExampleMouseEnter
            AddHandler mouseMoveButton.MouseLeave, AddressOf OnMosueExampleMouseLeave
// Create the UI elements.
StackPanel mouseMoveStackPanel = new StackPanel();
Button mouseMoveButton = new Button();

// Set properties on Button.
mouseMoveButton.Background = Brushes.AliceBlue;
mouseMoveButton.Content = "Button";

// Attach Buttons to StackPanel.
mouseMoveStackPanel.Children.Add(mouseMoveButton);

// Attach event handler.
mouseMoveButton.MouseEnter += new MouseEventHandler(OnMouseExampleMouseEnter);
mouseMoveButton.MouseLeave += new MouseEventHandler(OnMosueExampleMouseLeave);

La deuxième section de l'exemple est écrite dans le code et définit les gestionnaires d'événements. Lorsque la souris se trouve sur le bouton Button, la couleur Background du Button change SlateGray.. Lorsque la souris quitte le bouton Button, la couleur Background du Button revient à AliceBlue..

        Private Sub OnMouseExampleMouseEnter(ByVal sender As Object, ByVal e As MouseEventArgs)
            ' Cast the source of the event to a Button.
            Dim source As Button = TryCast(e.Source, Button)

            ' If source is a Button.
            If source IsNot Nothing Then
                source.Background = Brushes.SlateGray
            End If
        End Sub
private void OnMouseExampleMouseEnter(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.SlateGray;
    }
}
        Private Sub OnMosueExampleMouseLeave(ByVal sender As Object, ByVal e As MouseEventArgs)
            ' Cast the source of the event to a Button.
            Dim source As Button = TryCast(e.Source, Button)

            ' If source is a Button.
            If source IsNot Nothing Then
                source.Background = Brushes.AliceBlue
            End If
        End Sub
private void OnMosueExampleMouseLeave(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.AliceBlue;
    }
}

Entrée de texte

L'événement TextInput permet d'écouter une entrée de texte d'une manière indépendante du périphérique. Le clavier est le principal périphérique d'entrée de texte, mais la voix, l'écriture et d'autres périphériques d'entrée peuvent générer du texte également.

Pour l'entrée au clavier, WPF envoie en premier les événements KeyDown / KeyUp appropriés. Si ces événements ne sont pas gérés et qu'il s'agit de la touche d'une lettre (et non d'une touche de contrôle, telle que les touches de direction ou les touches de fonction), un événement TextInput se déclenche. Il n'existe pas toujours une association univoque simple entre des événements KeyDown/KeyUp et TextInput, car plusieurs séquences de touches peuvent générer un caractère unique et des séquences impliquant une seule touche peuvent générer des chaînes de plusieurs caractères. C'est particulièrement vrai pour le chinois, le japonais et le coréen, par exemple qui utilisent Input Method Editors (IMEs) pour générer des milliers de caractères dans leurs alphabets correspondants.

Lorsque WPF envoie un événement KeyUp/KeyDown, Key est affecté de la valeur Key.System si les séquences de touches peuvent faire partie d'un événement TextInput (si ALT+S est utilisé, par exemple). Ainsi, le code dans un gestionnaire d'événements KeyDown peut rechercher Key.System et, s'il le trouve, quitter le traitement du gestionnaire de l'événement déclenché TextInput par la suite. Dans ce cas, les propriétés de l'argument TextCompositionEventArgs peuvent être utilisées pour déterminer les séquences de touches d'origine. De la même, si un IME est actif, Key a la valeur Key.ImeProcessed et ImeProcessedKey donne la séquence ou les séquences de touches d'origine.

L'exemple suivant définit un gestionnaire pour l'événement Click et un gestionnaire pour l'événement KeyDown

Le premier segment du code ou de balise crée l'interface utilisateur.

<StackPanel KeyDown="OnTextInputKeyDown">
  <Button Click="OnTextInputButtonClick"
          Content="Open" />
  <TextBox> . . . </TextBox>
</StackPanel>
            ' Create the UI elements.
            Dim textInputStackPanel As New StackPanel()
            Dim textInputeButton As New Button()
            Dim textInputTextBox As New TextBox()
            textInputeButton.Content = "Open"

            ' Attach elements to StackPanel.
            textInputStackPanel.Children.Add(textInputeButton)
            textInputStackPanel.Children.Add(textInputTextBox)

            ' Attach event handlers.
            AddHandler textInputStackPanel.KeyDown, AddressOf OnTextInputKeyDown
            AddHandler textInputeButton.Click, AddressOf OnTextInputButtonClick
// Create the UI elements.
StackPanel textInputStackPanel = new StackPanel();
Button textInputeButton = new Button();
TextBox textInputTextBox = new TextBox();
textInputeButton.Content = "Open";

// Attach elements to StackPanel.
textInputStackPanel.Children.Add(textInputeButton);
textInputStackPanel.Children.Add(textInputTextBox);

// Attach event handlers.
textInputStackPanel.KeyDown += new KeyEventHandler(OnTextInputKeyDown);
textInputeButton.Click += new RoutedEventHandler(OnTextInputButtonClick);

Le deuxième segment du code contient les gestionnaires d'événements.

        Private Sub OnTextInputKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
            If e.Key = Key.O AndAlso Keyboard.Modifiers = ModifierKeys.Control Then
                handle()
                e.Handled = True
            End If
        End Sub

        Private Sub OnTextInputButtonClick(ByVal sender As Object, ByVal e As RoutedEventArgs)
            handle()
            e.Handled = True
        End Sub

        Public Sub handle()
            MessageBox.Show("Pretend this opens a file")
        End Sub
private void OnTextInputKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.O && Keyboard.Modifiers == ModifierKeys.Control)
    {
        handle();
        e.Handled = true;
    }
}

private void OnTextInputButtonClick(object sender, RoutedEventArgs e)
{
    handle();
    e.Handled = true;
} 

public void handle()
{
    MessageBox.Show("Pretend this opens a file");
}

Étant donné que les événements d'entrée propagent la route d'événement, StackPanel reçoit l'entrée quel que soit l'élément qui a le focus clavier. Le contrôle TextBox est notifié en premier et le gestionnaire OnTextInputKeyDown est appelé uniquement si la TextBox n'a pas géré l'entrée. Si l'événement PreviewKeyDown est utilisé à la place de l'événement KeyDown, le gestionnaire OnTextInputKeyDown est appelé en premier.

Dans cet exemple, la logique de gestion est écrite deux fois : une fois pour CTRL+O et une fois pour l'événement Click du bouton. Cela peut être simplifié en utilisant des commandes au lieu de gérer les événements d'entrée directement. Les commandes sont expliquées dans cette présentation et dans Vue d'ensemble des commandes.

Fonctions tactiles et manipulation

Du nouveau matériel et une API dans le système d'exploitation Windows 7 fournissent aux applications la capacité de recevoir simultanément l'entrée de plusieurs fonctions tactiles. WPF permet aux applications de détecter et de répondre aux entrées tactiles d'une façon similaire à un autre type d'entrée, telle que la souris ou le clavier, en déclenchant des événements lorsque les entrées tactiles se produisent.

WPF expose deux types d'événements lorsque les entrées tactiles se produisent : les événements tactiles et les événements de manipulation. Les événements tactiles fournissent des données brutes relatives à chaque doigt sur un écran tactile et à leur déplacement. Les événements de manipulation interprètent l'entrée comme certaines actions. Les deux types d'événements sont abordés dans cette section.

Composants requis

Vous avez besoin des composants suivants pour développer une application qui répond aux entrées tactiles.

  • Microsoft Visual Studio 2010.

  • Windows 7.

  • un périphérique, tel qu'un écran tactile, qui prend en charge l'interface tactile Windows.

Terminologie

Les termes suivants sont utilisés lorsque les fonctions tactiles sont abordées.

  • La fonction tactile est un type d'entrée d'utilisateur reconnue par Windows 7. Habituellement, les fonctions tactiles sont initiées en plaçant des doigts sur un écran tactile interactif. Notez que les périphériques tels que les pavés tactiles, qui sont courants sur les ordinateurs portables, ne prennent pas en charge les fonctions tactiles si le périphérique convertit simplement la position du doigt et le déplacement en entrée de souris.

  • L'interaction tactile multipoint est un événement tactile qui se produit simultanément à partir de plusieurs points. Windows 7 et WPF prennent en charge l'interaction tactile multipoint. Chaque fois que les fonctions tactiles sont abordées dans la documentation pour WPF, les concepts s'appliquent à l'interaction tactile multipoint.

  • Une manipulation se produit lorsque les entrées tactiles sont interprétées comme une action physique s'appliquant à un objet. Dans WPF, les événements de manipulation interprètent l'entrée comme une manipulation de traduction, d'expansion ou de rotation.

  • Un touch device représente un périphérique qui produit une entrée tactile (par exemple, à l'aide d'un seul doigt sur un écran tactile).

Contrôles qui répondent aux entrées tactiles

Vous pouvez faire défiler les contrôles suivants en faisant glisser un doigt sur ces derniers s'ils comportent un contenu non visible.

Le ScrollViewer définit la propriété jointe ScrollViewer.PanningMode qui vous permet de spécifier si le mouvement panoramique tactile est activé horizontalement, verticalement, les deux à la fois, ou si aucun des deux n'est activé. La propriété ScrollViewer.PanningDeceleration spécifie la rapidité avec laquelle le défilement ralentit lorsque l'utilisateur soulève le doigt de l'écran tactile. La propriété jointe ScrollViewer.PanningRatio spécifie le rapport de décalage de défilement pour traduire le décalage de manipulation.

Événements tactiles

Les classes de base, UIElement, UIElement3D et ContentElement définissent les événements auxquels vous pouvez vous abonner pour que votre application réponde aux entrées tactiles. Les événements tactiles sont utiles lorsque votre application interprète les fonctions tactiles comme des actions différentes de la manipulation d'objet. Par exemple, une application qui permet à un utilisateur de dessiner avec un ou plusieurs doigts s'abonnerait à des événements tactiles.

Les trois classes définissent les événements suivants, qui se comportent de la même façon indépendamment de la classe de définition.

À l'instar des événements de clavier et de souris, les événements tactiles sont des événements routés. Les événements qui commencent par Preview sont des événements de tunneling et les événements qui commencent par Touch sont des événements de propagation. Pour plus d'informations sur les événements routés, consultez Vue d'ensemble des événements routés. Lorsque vous gérez ces événements, vous pouvez obtenir la position de l'entrée, par rapport à tout élément, en appelant la méthode GetTouchPoint ou GetIntermediateTouchPoints.

Pour comprendre l'interaction entre les événements tactiles, considérez le scénario où un utilisateur place un doigt sur un élément, déplace le doigt dans l'élément, puis soulève le doigt de l'élément. L'illustration suivante décrit l'exécution des événements de propagation (les événements de tunneling sont omis pour plus de simplicité).

Événements tactiles

La séquence des événements tactiles.

La liste suivante décrit la séquence des événements présentés dans l'illustration précédente.

  1. L'événement TouchEnter a lieu une fois lorsque l'utilisateur place un doigt sur l'élément.

  2. L'événement TouchDown a lieu une fois.

  3. L'événement TouchMove se produit plusieurs fois pendant que l'utilisateur déplace le doigt dans l'élément.

  4. L'événement TouchUp a lieu une fois lorsque l'utilisateur soulève le doigt de l'élément.

  5. L'événement TouchLeave a lieu une fois.

Lorsque plus de deux doigts sont utilisés, les événements se produisent pour chaque doigt.

Événements de manipulation

Dans les cas où une application permet à un utilisateur de manipuler un objet, la classe UIElement définit des événements de manipulation. Contrairement aux événements tactiles qui signalent simplement la position de fonctions tactiles, les événements de manipulation signalent de quelle façon l'entrée peut être interprétée. Il existe trois types de manipulations, la traduction, l'expansion et la rotation. La liste suivante explique comment appeler les trois types de manipulations.

  • Placez un doigt sur un objet et déplacez le doigt à travers l'écran tactile pour appeler une manipulation de traduction. Cela déplace habituellement l'objet.

  • Placez deux doigts sur un objet et rapprochez-les ou éloignez-les l'un de l'autre pour appeler une manipulation d'expansion. Cela redimensionne habituellement l'objet.

  • Placez deux doigts sur un objet et faites pivoter les doigts l'un autour de l'autre pour appeler une manipulation de rotation. Cela fait pivoter habituellement l'objet.

Plusieurs types de manipulation peuvent se produire simultanément.

Lorsque les objets répondent aux manipulations, vous pouvez faire en sorte qu'ils semblent avoir de l'inertie. Vos objets simulent ainsi le monde physique. Par exemple, lorsque vous poussez un livre à travers une table, si vous le poussez assez fortement, le livre continuera à se déplacer une fois que vous l'aurez libéré. WPF vous permet de simuler ce comportement en déclenchant des événements de manipulation après que les doigts de l'utilisateur libèrent l'objet.

Pour plus d'informations sur la création d'une application qui permet à l'utilisateur de déplacer, redimensionner et faire pivoter un objet, consultez Procédure pas à pas : création de votre première application Touch.

UIElement définit les événements de manipulation suivants.

Par défaut, un UIElement ne reçoit pas ces événements de manipulation. Pour recevoir des événements de manipulation sur un UIElement, affectez à UIElement.IsManipulationEnabled la valeur true.

Chemin d'exécution des événements de manipulation

Considérez un scénario où un utilisateur « lance » un objet. L'utilisateur place un doigt sur l'objet, déplace le doigt à travers l'écran tactile sur une courte distance, puis soulève le doigt pendant qu'il se déplace. Ainsi, l'objet se déplacera sous le doigt de l'utilisateur et continuera à se déplacer après que l'utilisateur a soulevé le doigt.

L'illustration suivante décrit le chemin d'exécution des événements de manipulation et fournit des informations importantes sur chaque événement.

Événements de manipulation

La séquence de manipulation des événements.

La liste suivante décrit la séquence des événements présentés dans l'illustration précédente.

  1. L'événement ManipulationStarting se produit lorsque l'utilisateur place un doigt sur l'objet. Entre autres choses, cet événement vous permet de définir la propriété ManipulationContainer. Dans les événements suivants, la position de la manipulation sera relative au ManipulationContainer. Dans les autres événements que ManipulationStarting, cette propriété est en lecture seule, donc l'événement ManipulationStarting est la seule occurrence où vous pouvez définir cette propriété.

  2. L'événement ManipulationStarted se produit ensuite. Cet événement signale l'origine de la manipulation.

  3. L'événement ManipulationDelta se produit plusieurs fois au fil du déplacement des doigts d'un utilisateur sur un écran tactile. La propriété DeltaManipulation de la classe ManipulationDeltaEventArgs signale si la manipulation est interprétée comme un mouvement, une expansion ou une traduction. C'est à ce niveau que vous exécutez la plupart du travail de manipulation d'un objet.

  4. L'événement ManipulationInertiaStarting se produit lorsque les doigts de l'utilisateur perdent le contact avec l'objet. Cet événement vous permet de spécifier la décélération des manipulations pendant l'inertie. C'est ainsi que votre objet peut émuler des espaces physiques différents ou des attributs selon ce que vous choisissez. Par exemple, supposez que votre application est dotée de deux objets qui représentent des éléments dans le monde physique, et que l'un des deux est plus lourd que l'autre. Vous pouvez faire en sorte que l'objet le plus lourd décélère plus vite que l'objet le plus léger.

  5. L'événement ManipulationDelta a lieu plusieurs fois pendant que l'inertie se produit. Notez que cet événement se produit lorsque les doigts de l'utilisateur se déplacent à travers l'écran tactile et lorsque WPF simule l'inertie. En d'autres termes, ManipulationDelta se produit avant et après l'événement ManipulationInertiaStarting. La propriété ManipulationDeltaEventArgs.IsInertial signale si l'événement ManipulationDelta se produit pendant l'inertie, afin que vous puissiez vérifier cette propriété et exécuter différentes actions, selon sa valeur.

  6. L'événement ManipulationCompleted se produit lorsque la manipulation et une inertie quelconque se terminent. Autrement dit, après que tous les événements ManipulationDelta ont lieu, l'événement ManipulationCompleted se produit pour signaler que la manipulation est terminée.

Le UIElement définit aussi l'événement ManipulationBoundaryFeedback. Cet événement se produit lorsque la méthode ReportBoundaryFeedback est appelée dans l'événement ManipulationDelta. L'événement ManipulationBoundaryFeedback permet aux applications ou aux composants de fournir une rétroaction visuelle lorsqu'un objet atteint une limite. Par exemple, la classe Window gère l'événement ManipulationBoundaryFeedback permettant d'entraîner un léger déplacement de la fenêtre lorsqu'il y a contact avec son bord.

Vous pouvez annuler la manipulation en appelant la méthode Cancel sur les arguments d'événement dans tout événement de manipulation à l'exception de l'événement ManipulationBoundaryFeedback. Lorsque vous appelez Cancel, les événements de manipulation ne sont plus déclenchés et les événements de souris se produisent pour les fonctions tactiles. Le tableau suivant décrit la relation entre l'heure à laquelle la manipulation est annulée et les événements de souris qui se produisent.

Événement dans lequel l'annulation est appelée

Événements de souris qui se produisent pour une entrée qui s'est déjà produite

ManipulationStarting et ManipulationStarted

Événements mouse down

ManipulationDelta

Événements mouse down et mouse move

ManipulationInertiaStarting et ManipulationCompleted

Événements mouse down, mouse move et mouse up

Notez que si vous appelez Cancel lorsque la manipulation est en inertie, la méthode retourne la valeur false et l'entrée ne déclenche pas d'événements de souris.

Relation entre les événements tactiles et les événements de manipulation

Un UIElement peut toujours recevoir des événements tactiles. Lorsque la propriété IsManipulationEnabled a la valeur true, un UIElement peut recevoir à la fois des événements tactiles et des événements de manipulation. Si l'événement TouchDown n'est pas géré (autrement dit, si la propriété Handled a la valeur false), la logique de manipulation capture l'entrée tactile appliquée à l'élément et génère les événements de manipulation. Si la propriété Handled a la valeur true dans l'événement TouchDown, la logique de manipulation ne génère pas d'événements de manipulation. L'illustration suivante montre la relation entre les événements tactiles et les événements de manipulation.

Événements tactiles et événements de manipulation

Relation entre les événements tactiles et les événements de manipulation

La liste suivante décrit la relation entre les événements tactiles et les événements de manipulation qui sont présentés dans l'illustration précédente.

Focus

Il existe deux concepts principaux associés au focus dans WPF : le focus clavier et le focus logique.

Focus clavier

Le focus clavier fait référence à l'élément qui reçoit l'entrée au clavier. Un seul élément de l'ordinateur peut avoir le focus clavier. Dans WPF, IsKeyboardFocused, l'élément qui a le focus clavier sera affecté de true. La méthode statique KeyboardFocusedElement retourne l'élément qui a le focus clavier.

Le focus clavier peut être obtenu en accédant à un élément avec la touche Tab ou en cliquant avec le bouton de la souris sur certains éléments, tels qu'une TextBox. Le focus clavier peut également être obtenu par programmation en utilisant la méthode Focus sur la classe Keyboard. La méthode Focus essaie de donner le focus clavier à l'élément spécifié. L'élément retourné par Focus est l'élément qui a le focus clavier.

Pour qu'un élément obtienne le focus clavier, la propriété Focusable et les propriétés IsVisible doivent être affectées de la valeur true. Certaines classes, telles que Panel, ont false affecté par défaut à Focusable. Par conséquent, vous pouvez devoir affecter à cette propriété la valeur true pour que cet élément puisse obtenir le focus.

L'exemple suivant utilise Focus pour placer le focus clavier sur un Button. Il est recommandé de définir le focus initial dans le gestionnaire d'événements Loaded d'une application.

        Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Sets keyboard focus on the first Button in the sample.
            Keyboard.Focus(firstButton)
        End Sub
private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}

Pour plus d'informations sur le focus clavier, consultez Vue d'ensemble du focus.

Focus logique

Le focus logique fait référence à l'FocusManager.FocusedElement dans une portée de focus. Plusieurs éléments d'une application peuvent avoir le focus logique, mais un seul élément peut avoir le focus logique dans une portée de focus donnée.

Une portée de focus est un élément conteneur qui effectue le suivi de l'FocusedElement dans sa portée. Lorsque le focus quitte une portée de focus, l'élément ayant le focus perd le focus clavier, mais il conserve le focus logique. Lorsque le focus revient dans la portée de focus, l'élément ayant le focus obtient le focus clavier. Cela permet au focus clavier de changer entre des portées de focus et de s'assurer que l'élément ayant le focus dans la portée de focus continue d'avoir le focus lorsque le focus revient.

Un élément peut être converti en portée de focus en Extensible Application Markup Language (XAML) en affectant à la propriété attachée FocusManager IsFocusScope la valeur true, ou dans le code en définissant la propriété attachée à la méthode SetIsFocusScope.

L'exemple suivant convertit un StackPanel en portée de focus en définissant la propriété attachée IsFocusScope.

<StackPanel Name="focusScope1" 
            FocusManager.IsFocusScope="True"
            Height="200" Width="200">
  <Button Name="button1" Height="50" Width="50"/>
  <Button Name="button2" Height="50" Width="50"/>
</StackPanel>
            Dim focuseScope2 As New StackPanel()
            FocusManager.SetIsFocusScope(focuseScope2, True)
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);

Les classes dans WPF ayant des portées de focus par défaut sont Window, Menu, ToolBar et ContextMenu.

Un élément qui a le focus clavier a également le focus logique pour la portée de focus à laquelle il appartient. Par conséquent, la définition du focus dans un élément avec la méthode Focus dans la classe Keyboard ou les classes d'élément de base tente de donner à l'élément le focus clavier et le focus logique.

Pour déterminer l'élément ayant le focus dans une portée de focus, utilisez GetFocusedElement. Pour modifier l'élément ayant le focus d'une portée de focus, utilisez SetFocusedElement.

Pour plus d'informations sur le focus logique, consultez Vue d'ensemble du focus.

Position de la souris

L'entrée de l'API WPF fournit des informations utiles sur les espaces de coordonnée. Par exemple, la coordonnée (0,0) est la coordonnée supérieure gauche, mais de quel élément de l'arborescence ? L'élément qui correspond à la cible d'entrée ? L'élément que vous avez attaché au gestionnaire d'événements ? Ou autre chose ? Pour éviter toute confusion, l'entrée de l'API WPF implique que vous spécifiez votre système de référence lorsque vous travaillez avec les coordonnées obtenues à travers la souris. La méthode GetPosition retourne la coordonnée du pointeur de la souris par rapport à l'élément spécifié.

Capture de la souris

Les souris maintiennent spécifiquement une caractéristique modale appelée capture de la souris. La capture de la souris est utilisée pour maintenir un état d'entrée transitionnel lorsqu'une opération Glisser-déplacer démarre afin que les autres opérations qui impliquent la position affichée nominale du pointeur de la souris ne soient pas nécessairement exécutées. Lorsque la souris glisse, l'utilisateur ne peut pas cliquer sans abandonner la fonction Glisser-déplacer, ce qui rend les informations de pointage de la souris inappropriées lorsque la capture de la souris est détenue par l'origine du glissement. Le système d'entrée expose les APIs qui peuvent déterminer l'état de capture de la souris, ainsi que les APIs qui peuvent forcer la capture de la souris dans un élément spécifique, ou effacer l'état de capture de la souris. Pour plus d'informations sur les opérations Glisser-déplacer, consultez Vue d'ensemble du glisser-déplacer.

Commandes

Les commandes permettent de gérer l'entrée à un niveau plus sémantique que l'entrée de périphérique. Les commandes sont des directives simples, telles que Cut, Copy, Paste ou Open. Les commandes sont utiles pour centraliser la logique de commande. La même commande peut être accessible depuis un Menu, dans une ToolBar, ou via un raccourci clavier. Les commandes fournissent également un mécanisme permettant de désactiver des contrôles lorsque la commande devient indisponible.

RoutedCommand est l'implémentation WPF de ICommand. Lorsqu'un RoutedCommand est exécuté, un événement PreviewExecuted et un événement Executed sont déclenchés sur la cible de commande qui utilisent le tunneling et la propagation dans l'arborescence d'éléments comme tout autre entrée. Si aucune cible de commande n'est définie, l'élément avec le focus clavier devient la cible de la commande. La logique qui exécute la commande est attachée à une CommandBinding. Lorsqu'un événement Executed atteint une CommandBinding pour une commande spécifique, le ExecutedRoutedEventHandler dans la CommandBinding est appelé. Ce gestionnaire exécute l'action de la commande.

Pour plus d'informations sur l'exécution des commandes, consultez Vue d'ensemble des commandes.

WPF fournit une bibliothèque de commandes communes constituée des ApplicationCommands, MediaCommands, ComponentCommands, NavigationCommands et EditingCommands, mais vous pouvez définir votre propre bibliothèque.

L'exemple suivant indique comment définir un MenuItem pour que, lorsque l'utilisateur clique dessus, il appelle la commande Paste dans la TextBox, si la TextBox a le focus clavier.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>
            ' Creating the UI objects
            Dim mainStackPanel As New StackPanel()
            Dim pasteTextBox As New TextBox()
            Dim stackPanelMenu As New Menu()
            Dim pasteMenuItem As New MenuItem()

            ' Adding objects to the panel and the menu
            stackPanelMenu.Items.Add(pasteMenuItem)
            mainStackPanel.Children.Add(stackPanelMenu)
            mainStackPanel.Children.Add(pasteTextBox)

            ' Setting the command to the Paste command
            pasteMenuItem.Command = ApplicationCommands.Paste
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;

Pour plus d'informations sur les commandes dans WPF, consultez Vue d'ensemble des commandes..

Le système d'entrée et les éléments de base

Les événements d'entrée, tels que les événements attachés définis par les classes Mouse, Keyboard et Stylus sont déclenchés par le système d'entrée et injectés dans une position particulière dans le modèle objet selon le test de positionnement de l'arborescence visuelle au moment de l'exécution.

Chacun des événements que Mouse, Keyboard et Stylus définissent comme événement attaché est également ré-exposé par les classes d'élément de base UIElement et ContentElement sous la forme d'un nouvel événement routé. Les événements routés par les éléments de base sont générés par les classes qui gèrent l'événement attaché d'origine et qui réutilisent les données d'événement.

Lorsque l'événement d'entrée est associé à un élément source particulier à travers son implémentation d'événement d'entrée d'élément de base, il peut être routé à travers le reste d'un itinéraire d'événement basé sur une combinaison d'objets d'arborescences logique et visuelle et il peut être géré par le code d'application. En général, il est préférable de gérer ces événements d'entrée de périphérique à l'aide des événements routés dans UIElement et ContentElement, car vous pouvez utiliser une syntaxe de gestionnaire d'événements plus intuitive en XAML et dans le code. Vous pouvez décider de gérer l'événement attaché qui a initialisé à la place le processus, mais dans ce cas plusieurs problèmes apparaissent : l'événement attaché peut être marqué comme étant géré par la gestion de classe des éléments de base, et vous devez utiliser des méthodes d'accesseur plutôt qu'une vraie syntaxe d'événement pour joindre des gestionnaires pour les événements attachés.

Quoi d'autre ?

Vous connaissez maintenant plusieurs techniques de gestion des entrées dans WPF. Maintenant, vous devez aussi mieux comprendre les divers types d'événements d'entrée et les mécanismes des événements routés utilisés par WPF.

Des ressources supplémentaires, qui expliquent plus en détail les éléments d'infrastructure WPF et le routage des événements, sont disponibles. Pour plus d'informations à ce sujet, consultez les vues d'ensemble suivantes : Vue d'ensemble des commandes, Vue d'ensemble du focusVue d'ensemble des éléments de baseArborescences dans WPF, et Vue d'ensemble des événements routés.

Voir aussi

Concepts

Vue d'ensemble du focus

Vue d'ensemble des commandes

Vue d'ensemble des événements routés

Vue d'ensemble des éléments de base

Autres ressources

Propriétés