Partager via


Vue d'ensemble des entrées

le sous-système Windows Presentation Foundation (WPF) fournit une API puissante pour obtenir des entrées à partir d’un large éventail d’appareils, notamment la souris, le clavier, le toucher et le stylet. Cette rubrique décrit les services fournis par WPF et explique l’architecture des systèmes d’entrée.

API d’entrée

L’exposition de l’API d’entrée principale se trouve sur les classes d’éléments de base : UIElement, ContentElement, FrameworkElementet FrameworkContentElement. Pour plus d’informations sur les éléments de base, consultez Vue d’ensemble des éléments de base. Ces classes fournissent des fonctionnalités pour les événements d’entrée liés aux touches d’appui, aux boutons de la souris, à la roulette de la souris, au mouvement de la souris, à la gestion du focus et à la capture de souris, pour nommer quelques-uns. En plaçant l’API d’entrée sur les éléments de base, plutôt que de traiter tous les événements d’entrée en tant que service, l’architecture d’entrée permet aux événements d’entrée d’être sourcer par un objet particulier dans l’interface utilisateur et de prendre en charge un schéma de routage d’événements dans lequel plusieurs éléments ont la possibilité de gérer un événement d’entrée. De nombreux événements d’entrée ont une paire d’événements qui leur sont associés. Par exemple, l’événement d'appui sur la touche est associé aux événements KeyDown et PreviewKeyDown. La différence dans ces événements est la façon dont ils sont routés vers l’élément cible. Les événements de préversion 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 des événements dans WPF est abordé plus en détail plus loin dans cette vue d’ensemble et dans la vue d’ensemble des événements routés .

Classes clavier et souris

Outre l’API d’entrée sur les classes d’éléments de base, la classe Keyboard et les classes Mouse fournissent une API supplémentaire pour l’utilisation d’une entrée clavier et souris.

Les exemples d’API d’entrée sur la classe Keyboard sont la propriété Modifiers, qui retourne la ModifierKeys actuellement enfoncée et la méthode IsKeyDown, qui détermine si une touche spécifiée est enfoncée.

L’exemple suivant utilise la méthode GetKeyStates pour déterminer si un Key est dans l’état inférieur.

// 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;
}
' 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

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

L’exemple suivant détermine si l'LeftButton sur la souris est dans l’état Pressed.

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

Les classes Mouse et Keyboard sont abordées plus en détail dans cette vue d’ensemble.

Entrée de stylet

WPF a intégré la prise en charge du Stylus. Le Stylus est une saisie effectuée à l'aide du stylet popularisée par la Tablette PC. Les applications WPF peuvent traiter le stylet comme une souris à l’aide de l’API de la souris, mais WPF expose également une abstraction d’appareil de stylet qui utilise un modèle similaire au clavier et à la souris. Toutes les API liées au stylet contiennent le mot « Stylet ».

Étant donné que le stylet peut agir comme une souris, les applications qui prennent en charge uniquement l’entrée de la souris peuvent toujours obtenir un certain niveau de prise en charge automatique du stylet. Lorsque le stylet est utilisé de telle manière, l’application a la possibilité de gérer l’événement de stylet approprié, puis de gérer l’événement de souris correspondant. En outre, les services de niveau supérieur tels que l’entrée d’encre sont également disponibles grâce à l’abstraction du stylet. Pour plus d’informations sur l’encre comme entrée, consultez Bien démarrer avec l’encre.

Routage des événements

Un FrameworkElement peut contenir d’autres éléments (comme des éléments enfants) dans son modèle de contenu, formant ainsi une arborescence d’éléments. Dans WPF, l’élément parent peut participer à l’entrée dirigée vers ses éléments enfants ou d’autres descendants en partageant des événements. Cela est particulièrement utile pour créer des contrôles à partir de contrôles plus petits, un processus appelé « composition de contrôles » ou « compositage ». Pour plus d’informations sur les arborescences d’éléments et la façon dont les arborescences d’éléments se rapportent aux chemins d’événements, consultez Trees dans WPF.

Le routage des événements est le processus de transfert d’événements vers plusieurs éléments, afin qu’un objet ou un élément particulier le long de l’itinéraire puisse choisir d’offrir une réponse significative (par le biais de la gestion) à un événement qui a peut-être été source par un autre élément. Les événements routés utilisent l’un des trois mécanismes de routage suivants : direct, par propagation et par tunneling. Dans le routage direct, l’élément source est le seul élément averti et l’événement n’est pas routé vers d’autres éléments. Toutefois, l’événement routé direct offre toujours certaines fonctionnalités 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 d’abord l’élément à l’origine de l’événement, puis l’élément parent, et ainsi de suite. Le tunneling commence à la racine de l’arborescence d’éléments puis descend, en finissant à 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 se présentent généralement sous la forme de paires composé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 « Préversion ». Par exemple, PreviewMouseMove est la version tunneling d'un événement de déplacement de la souris et MouseMove est la version bubbling de cet événement. Ce jumelage d’événements est une convention implémentée au niveau de l’élément et qui n’est pas une fonctionnalité inhérente du système d’événements WPF. Pour plus d’informations, consultez la section Événements d’entrée WPF dans Vue d’ensemble des événements routés.

Gestion des événements d’entrée

Pour recevoir une entrée sur un élément, un gestionnaire d’événements doit être associé à cet événement particulier. En XAML, cela est simple : vous référencez le nom de l’événement en tant qu’attribut de l’élément qui sera à l’écoute de cet événement. Vous devez ensuite attribuer à l'attribut le nom du gestionnaire d'événements que vous avez défini en fonction d'un délégué. Le gestionnaire d’événements doit être écrit dans du code tel que C# et peut être inclus dans un fichier code-behind.

Les événements clavier se produisent lorsque le système d’exploitation signale des actions clés qui se produisent pendant que le focus clavier se trouve sur un élément. Les événements souris et stylet entrent chacun dans deux catégories : les événements qui signalent les modifications apportées à la position du pointeur par rapport à l’élément et les événements qui signalent des modifications dans l’état des boutons de l’appareil.

Exemple d’événement d’entrée clavier

L’exemple suivant détecte un appui sur la touche de direction gauche. Un StackPanel est créé avec un Button. Un gestionnaire d’événements pour détecter la touche de direction gauche est attaché à l’instance de Button.

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

<StackPanel>
  <Button Background="AliceBlue"
          KeyDown="OnButtonKeyDown"
          Content="Button1"/>
</StackPanel>
// 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);
' 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

La deuxième section est écrite dans le code et définit le gestionnaire d’événements. Lorsque la touche de direction gauche est enfoncée et que le Button a le focus clavier, le gestionnaire s’exécute et la couleur Background du Button est modifiée. Si la touche est enfoncée, mais qu’elle n’est pas la flèche gauche, la couleur Background du Button est remplacée par sa couleur de départ.

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;
        }
    }
}
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

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

Dans l’exemple suivant, la couleur Background d’un Button est modifiée lorsque le pointeur de la souris entre dans le Button. La couleur Background est restaurée lorsque la souris quitte le Button.

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

<StackPanel>
  <Button Background="AliceBlue"
          MouseEnter="OnMouseExampleMouseEnter"
          MouseLeave="OnMosueExampleMouseLeave">Button
          
  </Button>
</StackPanel>
// 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);
' 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

La deuxième section de l’exemple est écrite dans le code et définit les gestionnaires d’événements. Lorsque la souris entre dans la Button, la couleur Background du Button est remplacée par SlateGray. Lorsque la souris quitte le Button, la couleur Background du Button est remplacée par AliceBlue.

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 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 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;
    }
}
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

Entrée de texte

L’événement TextInput vous permet d’écouter l’entrée de texte de manière indépendante de l’appareil. Le clavier est le moyen principal d’entrée de texte, mais la parole, l’écriture manuscrite et d’autres périphériques d’entrée peuvent également générer une entrée de texte.

Pour l’entrée au clavier, WPF envoie d’abord les événements de KeyDown/KeyUp appropriés. Si ces événements ne sont pas gérés et que la clé est textuelle (plutôt qu’une touche de contrôle telle que des flèches directionnelles ou des touches de fonction), un événement TextInput est déclenché. Il n’existe pas toujours de mappage simple un-à-un entre les événements KeyDown/KeyUp et TextInput, car plusieurs séquences de touches peuvent générer un seul caractère d’entrée de texte et des séquences de touches uniques peuvent générer des chaînes à caractères multiples. Cela est particulièrement vrai pour les langues telles que le chinois, le japonais et le coréen qui utilisent les éditeurs de méthode d’entrée (IMEs) pour générer les milliers de caractères possibles dans leurs alphabets correspondants.

Lorsque WPF envoie un événement de KeyUp/KeyDown, Key est défini sur Key.System si les séquences de touches peuvent faire partie d’un événement TextInput (si ALT+S est appuyé, par exemple). Cela permet au code d’un gestionnaire d’événements KeyDown de rechercher Key.System et, s'il est trouvé, de laisser le traitement au gestionnaire de l'événement TextInput déclenché subséquemment. Dans ces cas, les différentes propriétés de l’argument TextCompositionEventArgs peuvent être utilisées pour déterminer les séquences de touches d’origine. De même, si un IME est actif, Key a la valeur de Key.ImeProcessed, et ImeProcessedKey donne la séquence de touches 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 de code ou de balisage crée l’interface utilisateur.

<StackPanel KeyDown="OnTextInputKeyDown">
  <Button Click="OnTextInputButtonClick"
          Content="Open" />
  <TextBox> . . . </TextBox>
</StackPanel>
// 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);
' 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

Le deuxième segment de code contient les gestionnaires d’événements.

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");
}
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

Comme les événements d’entrée se propagent vers le haut le long de l’itinéraire d’événement, le StackPanel reçoit l’entrée quel que soit l’élément ayant le focus clavier. Le contrôle TextBox est averti en premier et le gestionnaire OnTextInputKeyDown est appelé uniquement si le TextBox n’a pas géré l’entrée. Si l’événement PreviewKeyDown est utilisé au lieu 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, puis à nouveau pour l’événement click du bouton. Cela peut être simplifié à l’aide de commandes, au lieu de gérer directement les événements d’entrée. Les commandes sont décrites dans cette vue d’ensemble et dans Vue d’ensemble de la commande.

Interaction tactile et manipulation

Le nouveau matériel et l’API dans le système d’exploitation Windows 7 offrent aux applications la possibilité de recevoir des entrées de plusieurs touches simultanément. WPF permet aux applications de détecter et de répondre aux interactions tactiles de manière similaire à la réponse à d’autres entrées, telles que la souris ou le clavier, en déclenchant des événements lorsque l’interaction tactile se produit.

WPF expose deux types d’événements lorsque l’interaction tactile se produit : les événements tactiles et les événements de manipulation. Les événements tactiles fournissent des données brutes sur chaque doigt sur un écran tactile et son mouvement. 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.

Conditions préalables

Vous avez besoin des composants suivants pour développer une application qui répond à l’interaction tactile.

  • Visual Studio 2010.

  • Windows 7.

  • Un appareil, tel qu’un écran tactile, qui prend en charge Windows Touch.

Terminologie

Les termes suivants sont utilisés lorsque l’interaction tactile est abordée.

  • Touch est un type d’entrée utilisateur reconnu par Windows 7. En règle générale, l’interaction tactile est lancée en plaçant les doigts sur un écran tactile. Notez que les appareils tels qu’un pavé tactile courant sur les ordinateurs portables ne prennent pas en charge l’interaction tactile si l’appareil convertit simplement la position et le mouvement du doigt comme entrée de souris.

  • L’interaction tactile multipoint est une entrée tactile qui se produit simultanément à partir de plusieurs points. Windows 7 et WPF prennent en charge l’interaction tactile multipoint. Chaque fois que le toucher est abordé dans la documentation de WPF, les concepts s'appliquent à l'interaction multitactile.

  • Une manipulation se produit quand l’entrée tactile est interprétée comme une action physique appliquée à 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 appareil qui produit une entrée tactile, telle qu’un seul doigt sur un écran tactile.

Contrôles qui répondent à l’interaction tactile

Les contrôles suivants peuvent faire défiler l’écran en faisant glisser un doigt sur le contrôle s’il contient du contenu qui est sorti de l’affichage.

Le ScrollViewer définit la propriété jointe ScrollViewer.PanningMode, qui vous permet de spécifier si le panoramique tactile est activé horizontalement, verticalement, à la fois ou pas du tout. La propriété ScrollViewer.PanningDeceleration spécifie la vitesse à laquelle le défilement ralentit lorsque l’utilisateur lève le doigt à partir 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 d’interaction tactile

Les classes de base, UIElement, UIElement3Det ContentElement, définissent les événements auxquels vous pouvez vous abonner afin que votre application réponde à l’interaction tactile. Les événements tactiles sont utiles lorsque votre application interprète l’interaction tactile comme autre que la manipulation d’un 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, quelle que soit la classe de définition.

Comme les événements de clavier et de souris, les événements d’interaction tactile 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 à n’importe quel élément, en appelant la méthode GetTouchPoint ou GetIntermediateTouchPoints.

Pour comprendre l’interaction entre les événements tactiles, envisagez le scénario où un utilisateur place un doigt sur un élément, déplace le doigt dans l’élément, puis lève le doigt de l’élément. L’illustration suivante montre l’exécution des événements de propagation (les événements de tunneling sont omis par souci de simplicité).

Séquence d’événements tactiles. Événements tactiles

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

  1. L’événement TouchEnter se produit une fois lorsque l’utilisateur met un doigt sur l’élément.

  2. L’événement TouchDown se produit une fois.

  3. L’événement TouchMove se produit plusieurs fois lorsque l’utilisateur déplace le doigt dans l’élément.

  4. L’événement TouchUp se produit une fois lorsque l’utilisateur lève le doigt de l’élément.

  5. L’événement TouchLeave se produit 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 l’interaction tactile, les événements de manipulation indiquent comment l’entrée peut être interprétée. Il existe trois types de manipulations, de traduction, d’expansion et de rotation. La liste suivante décrit comment appeler les trois types de manipulations.

  • Placez un doigt sur un objet et déplacez le doigt sur l’écran tactile pour appeler une manipulation de traduction. Cela déplace généralement l’objet.

  • Placez deux doigts sur un objet et déplacez les doigts de plus en plus près des uns des autres pour appeler une manipulation d’expansion. Cela redimensionne généralement l’objet.

  • Placez deux doigts sur un objet et faites pivoter les doigts les uns autour des autres pour appeler une manipulation de rotation. Cela fait généralement pivoter l’objet.

Plusieurs types de manipulation peuvent se produire simultanément.

Lorsque vous faites en sorte que des objets répondent à des manipulations, vous pouvez faire apparaître l'objet comme ayant de l'inertie. Cela peut faire en sorte que vos objets simulent le monde physique. Par exemple, lorsque vous poussez un livre sur une table, si vous poussez suffisamment fort, le livre continuera à se déplacer après l'avoir relâché. WPF vous permet de simuler ce comportement en activant des événements de manipulation après que les doigts de l’utilisateur relâchent l’objet.

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

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

Par défaut, une UIElement ne reçoit pas ces événements de manipulation. Pour recevoir des événements de manipulation sur UIElement, définissez UIElement.IsManipulationEnabled sur true.

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

Envisagez un scénario dans lequel un utilisateur « lève » un objet. L’utilisateur met un doigt sur l’objet, déplace le doigt sur l’écran tactile pendant une courte distance, puis lève le doigt pendant qu’il se déplace. Le résultat est que l’objet se déplace sous le doigt de l’utilisateur et continue à se déplacer après que l’utilisateur lève le doigt.

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

Séquence d’événements de manipulation. Événements de manipulation

La liste suivante décrit la séquence des événements 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 événements autres que ManipulationStarting, cette propriété est en lecture seule. Par conséquent, l’événement ManipulationStarting est la seule fois que 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 lorsque les doigts d’un utilisateur se déplacent sur un écran tactile. La propriété DeltaManipulation de la classe ManipulationDeltaEventArgs indique si la manipulation est interprétée comme un mouvement, une expansion ou une traduction. C’est là que vous effectuez la plupart du travail de manipulation d’un objet.

  4. L’événement ManipulationInertiaStarting se produit lorsque les doigts de l’utilisateur perdent contact avec l’objet. Cet événement vous permet de spécifier la décélération des manipulations pendant l’inertie. C’est pourquoi votre objet peut émuler différents espaces physiques ou attributs si vous le souhaitez. Par exemple, supposons que votre application a deux objets qui représentent des éléments dans le monde physique, et qu’une est plus lourde que l’autre. Vous pouvez rendre l’objet plus lourd décélérer plus rapidement que l’objet plus léger.

  5. L’événement ManipulationDelta se produit plusieurs fois au fur et à mesure que l’inertie se produit. Notez que cet événement se produit lorsque les doigts de l’utilisateur se déplacent sur l’écran tactile et lorsque WPF simule l’inertie. En d’autres termes, ManipulationDelta se produit avant et après l’événement de ManipulationInertiaStarting. La propriété ManipulationDeltaEventArgs.IsInertial indique si l’événement ManipulationDelta se produit pendant l’inertie. Vous pouvez donc vérifier cette propriété et effectuer différentes actions, en fonction de sa valeur.

  6. L’événement ManipulationCompleted se produit lorsque la manipulation et toute inertie se termine. Autrement dit, une fois que tous les événements ManipulationDelta se produisent, l’événement ManipulationCompleted se produit pour signaler que la manipulation est terminée.

Le UIElement définit également 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 des commentaires visuels lorsqu’un objet atteint une limite. Par exemple, la classe Window gère l’événement ManipulationBoundaryFeedback pour que la fenêtre se déplace légèrement lorsque son bord est rencontré.

Vous pouvez annuler la manipulation en appelant la méthode Cancel sur les arguments d’événement dans n’importe quel événement de manipulation, sauf ManipulationBoundaryFeedback'événement. Lorsque vous appelez Cancel, les événements de manipulation ne sont plus déclenchés et les événements de souris se produisent en réponse à l’interaction tactile. Le tableau suivant décrit la relation entre l'heure d'annulation de la manipulation et les événements de la souris qui se produisent.

Événement pendant lequel Annuler est appelé Les événements de souris qui se produisent pour une entrée qui a déjà eu lieu.
ManipulationStarting et ManipulationStarted Événements souris enfoncée.
ManipulationDelta Événements souris enfoncée et souris déplacée.
ManipulationInertiaStarting et ManipulationCompleted Événements souris enfoncée, souris déplacée et souris relâchée.

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

La relation entre les événements de contact et de manipulation

Un UIElement peut toujours recevoir des événements tactiles. Lorsque la propriété IsManipulationEnabled est définie sur true, un UIElement peut recevoir des événements tactiles et de manipulation. Si l’événement TouchDown n’est pas géré (autrement dit, la propriété Handled est false), la logique de manipulation capture l’interaction tactile sur l’élément et génère les événements de manipulation. Si la propriété Handled est définie sur 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.

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

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

Focus

Il existe deux concepts principaux relatifs 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 du clavier. Il ne peut y avoir qu’un seul élément sur l’ensemble du bureau recevant le focus du clavier. Dans WPF, l’élément qui a le focus clavier aura IsKeyboardFocused réglé à true. La méthode statique KeyboardFocusedElement retourne l’élément qui a actuellement le focus du clavier.

Le focus clavier peut être obtenu en accédant à un élément par tabulation ou en cliquant avec la souris sur certains éléments, par exemple un TextBox. Le focus clavier peut également être obtenu par programmation à l’aide de la méthode Focus sur la classe Keyboard. Focus tente de donner le focus du clavier à l’élément spécifié. L’élément retourné par Focus est l’élément qui a actuellement le focus du clavier.

Pour qu'un élément obtienne le focus clavier, la propriété Focusable ainsi que les propriétés IsVisible doivent être réglées sur la valeur true. Certaines classes, telles que Panel, ont Focusable définie sur false par défaut ; par conséquent, vous devrez peut-être définir cette propriété sur true si vous souhaitez que cet élément puisse obtenir le focus.

L’exemple suivant utilise Focus pour définir le focus clavier sur un Button. L’emplacement recommandé pour définir le focus initial dans une application se trouve dans le gestionnaire d’événements Loaded.

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}
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

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

Focus logique

Le focus logique fait référence au FocusManager.FocusedElement dans une étendue de focus. Il peut y avoir plusieurs éléments qui ont le focus logique dans une application, mais il ne peut y avoir qu’un seul élément qui a le focus logique dans une étendue de focus particulière.

Une étendue de focus est un élément conteneur qui effectue le suivi du FocusedElement dans son étendue. Quand le focus quitte une étendue de focus, l’élément ayant le focus perd le focus clavier, mais conserve le focus logique. Quand 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 étendues de focus, et de s’assurer que l’élément ayant le focus dans l’étendue de focus demeure l’élément ayant le focus quand le focus revient.

Un élément peut être transformé en une étendue de focus dans XAML (Extensible Application Markup Language) en définissant la propriété jointe FocusManagerIsFocusScope sur true, ou dans le code en définissant la propriété jointe à l’aide de la méthode SetIsFocusScope.

L’exemple suivant transforme un StackPanel en une portée de focus en définissant la propriété associé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>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);
Dim focuseScope2 As New StackPanel()
FocusManager.SetIsFocusScope(focuseScope2, True)

Les classes dans WPF qui sont des étendues de focus par défaut sont Window, Menu, ToolBaret ContextMenu.

Un élément qui a le focus clavier a également le focus logique pour l’étendue de focus à laquelle il appartient. Par conséquent, si vous définissez le focus sur un élément avec la méthode Focus sur la classe Keyboard ou les classes d’éléments de base, le système tentera de donner à l’élément le focus clavier et le focus logique.

Pour déterminer l’élément ciblé dans une étendue de focus, utilisez GetFocusedElement. Pour modifier l’élément prioritaire pour une étendue de focus, utilisez SetFocusedElement.

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

Position de la souris

L’API d’entrée WPF fournit des informations utiles concernant les espaces de coordonnées. Par exemple, la coordonnée (0,0) est la coordonnée supérieur gauche, mais de quel élément dans l’arborescence ? L’élément qui est la cible d’entrée ? Élément auquel vous avez attaché votre gestionnaire d’événements ? Ou quelque chose d’autre ? Pour éviter toute confusion, l’API d’entrée WPF nécessite que vous spécifiiez votre cadre de référence lorsque vous travaillez avec des coordonnées obtenues via la souris. La méthode GetPosition retourne la coordonnée du pointeur de la souris par rapport à l’élément spécifié.

Capture de souris

Les appareils de souris contiennent spécifiquement une caractéristique modale connue sous le nom de capture de souris. La capture de la souris est utilisée pour maintenir un état d’entrée transitionnel lorsqu’une opération de glisser-déplacer est démarrée, afin que d’autres opérations impliquant la position nominale à l’écran du pointeur de la souris ne se produisent pas nécessairement. Pendant l’opération de glisser, l’utilisateur ne peut pas cliquer sans annuler le glisser-déplacer, ce qui rend la plupart des indices de survol de souris inappropriés pendant que la capture de la souris est détenue par l’origine de l’opération glisser. Le système d’entrée expose les API qui peuvent déterminer l’état de capture de la souris, ainsi que les API qui peuvent forcer la capture de la souris à un élément spécifique ou effacer l’état de capture de la souris. Pour plus d’informations sur les opérations de glisser-déplacer, consultez Vue d’ensemble du glisser-déplacer.

Commandes

Les commandes permettent la gestion des entrées au niveau sémantique supérieur à l’entrée de l’appareil. Les commandes sont des directives simples, telles que Cut, Copy, Pasteou Open. Les commandes sont utiles pour centraliser votre logique de commande. La même commande peut être accessible à partir d’un Menu, sur un ToolBarou via un raccourci clavier. Les commandes fournissent également un mécanisme permettant de désactiver les contrôles lorsque la commande devient indisponible.

RoutedCommand est l’implémentation WPF de ICommand. Lorsqu’un RoutedCommand est exécuté, un PreviewExecuted et un événement Executed sont déclenchés sur la cible de commande, qui transitent et remontent à travers l'arborescence des éléments comme d'autres entrées. Si une cible de commande n’est pas définie, l’élément avec focus clavier est la cible de commande. La logique qui exécute la commande est attachée à un CommandBinding. Lorsqu’un événement Executed atteint un CommandBinding pour cette commande spécifique, le ExecutedRoutedEventHandler sur le CommandBinding est appelé. Ce gestionnaire effectue l’action de la commande.

Pour plus d’informations sur la commande, consultez Vue d’ensemble des commandes.

WPF fournit une bibliothèque de commandes courantes qui se composent de ApplicationCommands, MediaCommands, ComponentCommands, NavigationCommandset EditingCommands, ou vous pouvez définir vos propres.

L’exemple suivant montre comment configurer un MenuItem afin qu’en cliquant dessus, il appelle la commande Paste sur le TextBox, en supposant que le TextBox a le focus clavier.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>
// 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;
' 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

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 en fonction des tests de résultats effectués sur l’arborescence d’éléments visuels au moment de l’exécution.

Chacun des événements que Mouse, Keyboardet Stylus définit comme un événement attaché est également re-exposé en tant qu’événement routé par les classes d’éléments de base UIElement et ContentElement. Les événements routés par l’élément de base sont générés par des classes qui gèrent l’événement attaché d’origine et réutilisant les données d’événement.

Lorsque l’événement d’entrée devient associé à un élément source particulier par le biais de son implémentation d’événement d’entrée d’élément de base, il peut être routé via le reste d’un itinéraire d’événement basé sur une combinaison d’objets d’arborescence logique et visuelle, et être géré par le code d’application. En règle générale, il est plus pratique de gérer ces événements d’entrée liés à l’appareil à l’aide des événements routés sur UIElement et ContentElement, car vous pouvez utiliser une syntaxe de gestionnaire d’événements plus intuitive à la fois en XAML et en code. Vous pouvez choisir de gérer l’événement attaché qui a lancé le processus à la place, mais vous rencontrez plusieurs problèmes : l’événement attaché peut être marqué comme géré par la gestion des classes d’éléments de base, et vous devez utiliser des méthodes d’accesseur plutôt que la syntaxe d’événement true afin d’attacher des gestionnaires pour les événements attachés.

Nouveautés suivantes

Vous avez maintenant plusieurs techniques pour gérer les entrées dans WPF. Vous devez également avoir une meilleure compréhension des différents types d’événements d’entrée et des mécanismes d’événements routés utilisés par WPF.

Des ressources supplémentaires sont disponibles pour expliquer plus en détail les éléments de l’infrastructure WPF et le routage des événements. Consultez les présentations suivantes pour plus d’informations, Vue d’ensemble des commandes, Vue d’ensemble desFocus, Vue d’ensemble des éléments de base, arborescences dans WPFet Vue d’ensemble des événements routés.

Voir aussi