[WPF] Amélioration du MultiTouch avec WPF 4
L’arrivée du Framework 4 entrainant celle aussi du WPF 4 va être une très bonne alternative pour pallier aux difficultés rencontrées dans le développement d’application Multi-touch avec le précèdent Framework ( 3.5 ) . En effet, il appartient aux nouveautés que le WPF 4 intègre de base des évènements de manipulation qui sont implémentés sur les UIElements. Ainsi que l’apparition d’un nouveau contrôle ( Scatter View ) mais aussi la mise à jour pour le support du Multi-Touch du ScrollViewer.
Effectivement l’interface tactile n’est pas novice pour Microsoft Windows puisque Vista intégrait auparavant de nombreuses directives Multi-touch. L’utilisation du WPF 2 est une preuve récurrente de cet technologie sous cet ancien système d’exploitation.
On retrouve toujours certains évènement utiliser sur le Framework 4 comme StylusEnter, StylusMove, StylusUp.
Preuve que l’innovation tactile a déjà été pensé sous Vista mais n’ayant pas su tirer le meilleur partie de cette innovation Windows 7 et l’arrive du WPF 4 apporte de réel opportunité de faire de nos applications des interfaces beaucoup plus riches.
Découverte du contrôle ScatterView
Pour commencer cette découverte du Mutlti-touch nous allons faire une analyse rapide et simple du contrôle mis à notre disposition par le Framework 4. Le Scatter View est un contrôle issue du Surface qui permet une vision des photos très agréables avec une interface tactile. Ce contrôle est disponible dans Microsoft.Windows.Controls de base mais bien entendu n’oublions pas de rajouté la dll du ScatterView disponible dans le Trainning Kit de Visual Studio 2010. Et ainsi après déclaration du ScatterView et des images on obtient une interface graphique déjà toute prête tant par les manipulations que par la gestion des Zooms, translation etc … Dans la continuité de notre logique ajouté impérativement l’assembly
1: xmlns:s="clr-namespace:Microsoft.Windows.Controls;assembly=ScatterView"
Inutiles de s’attarder sur ce contrôle étant donné que son fonctionnement est identique à Surface.
Développement avancé – Présentation des nouveaux évènements
Rentrons plus dans le vif du sujet en créant à la main une sorte de ScatterView grâce non pas au contrôle prédéfinit mais plutôt par l’intermédiaire des nouveaux évènements.
Pour avoir un aperçu de tous ces évènements rendez-vous dans Object browser de votre Visual Studio 2010 et rentrer manipulation dans la barre de recherche ( voir figure 1 )
- ManipulationStarted
- ManipulationDelta ( certainement le plus utilisé )
- ManipulationStarting
- ManipulationCompleted
Maintenant que vous avez à l’esprit une idée de ces évènements, il vous faut bien entendu mettre en place l’interface graphique de votre application en disposant par exemple quelques photos dans un Canvas. N’oublier surtout pas de nommé votre Canvas ( Nous l’avons appelé canvasContenu ).
Ensuite vous allez remarquer que dans les attributs d’une image une nouvelle propriété est à notre disposition. « ManipulationMode » définissant ainsi le type de Multi-Touch souhaitez ( Translation, rotation, Zoom … ).
1: <Image Source="1.jpg" Width="300" Height="300" ManipulationMode="All"/>
Cependant vous vous demandez surement comment nous allons modifier les coordonnées de l’image lors des Manipulations. Et bien l’utilisation de matrice nous est indispensable et elle s’appliquera donc à toutes nos images automatiquement car nous n’agissons pas sur chaque image à son tour mais sur le canvas qui les contient toutes, tout en établissant aussi la position de cette matrice comme suit :
1: <Canvas.Resources>
2: <MatrixTransform x:Key="Matrice">
3: <MatrixTransform.Matrix>
4: <Matrix OffsetX="350" OffsetY="350"/>
5: </MatrixTransform.Matrix>
6: </MatrixTransform>
7: </Canvas.Resources>
Il faut par la suite appliquer la matrice et sa transformation aux images, afin de pouvoir implémenter les différentes transformations à la suite de manipulation à l’image en cours de traitements. Pour cela nous n’avons qu’à rajouter la propriété permettant cette liaison dans les contrôles image.
1: RenderTransform="{StaticResource Matrice}"
Une fois toute la partie graphique mise en place, nous allons gérer nos évènements en code métier. Et qui dit code métier dit C#. Tout d’abord voici un aperçu de la déclaration de notre évènement que l’on a appelé ManipulationImage, en paramètre nous aurons object sender comme tout évènement mais aussi ManipulationDeltaEventArgs. Mais que signifie ce delta ? Est bien il correspond à la valeur par défaut du commutateur ainsi le message de geste est général, c’est-à-dire que nous n’avons pas de début et de fin.
1: private void ManipulationImage (object sender, ManipulationDeltaEventArgs e)
Les transformations découlant des manipulations seront donc déclarées entre les balises de cet évènement. Mais dans un premier temps nous allons récupérer les nouvelles coordonnées par rapport à notre canvas, grâce à GetDeltaManipulation qui va retourner les changements les plus récent réaliser lors de la dernière manipulation. Puis on récupère par la même occasion l’image manipulé. Celle qui sera donc modifiée sous l’action des doigts de l’utilisateur.
1: Manipulation m = e.GetDeltaManipulation(canvasContenu);
2: Image monImageMan = e.OriginalSource as Image;
Ensuite, nous en déduisons sa matrice afin de pouvoir altérer ses coordonnées et ainsi pouvoir lui affecter et appliquer toutes les transformations subit .
1: var matrice = ((MatrixTransform)monImageMan.RenderTransform).Matrix;
2: var orgCenter = new Point(monImageMan.ActualWidth / 2,
monImageMan.ActualHeight / 2);
Maintenant il nous reste donc plus qu’à définir qu’elle transformation fera quoi. Garder à l’esprit que les transformations agissent sur la matrice et non sur les propriétés de l’image directement .
1: //Translation
2: matrice.Translate(m.Translation.X, m.Translation.Y);
3: var center = matrice.Transform(orgCenter);
4:
5: //Rotation
6: matrice.RotateAt(m.Rotation, center.X, center.Y);
7: center = matrice.Transform(orgCenter);
8:
9: //Zoom/Dezoom
10: matrice.ScaleAt(m.Scale, m.Scale, center.X, center.Y);
Enfin, il est logique que travailler sur une seule matrice sera impossible avec plusieurs images. Il y aurait un très gros problème une fois les transformations appliqué à une image pour en manipulé une autre. Pour résoudre cet inconvénient majeur rien de plus simple que de créer une nouvelle matrice à chaque nouvelle manipulation étant donné que au début nous récupérons les coordonnées qui seront modifiés ou non par une quelconque manipulation antérieur.
1: monImageMan.RenderTransform = new MatrixTransform(matrice);
2: e.Handled = true;
Comme expliquer précédemment ManipulationDelta va être solliciter par notre part. Néanmoins vous remarquerez que les évènements ainsi que toutes manipulations n’est pas fonctionnels. Nous allons rajouter une propriété clé dans notre application qui va permettre de gérer l’évènement manipulation en code métier. Dans les balises directement de notre application en XAML, nous devons lui informer que nous allons utiliser les manipulations en le déclarant de la sorte ManipulationDelta= Image_ManipulationDelta.
1: <Window x:Class="ApplicationTouchWPF4.Window1"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: Title="Window1" ManipulationDelta="Image_ManipulationDelta">
En estimant que Windows 7 et WPF 4 vont probablement être une des plates-formes les plus communes pour développer des applications de Multi-touch, il a de quoi surprendre vos amis. Sachant de plus que le tactile est une technologie en total expansion.
![clip_image002[12] clip_image002[12]](http://blogs.dotnet-france.com/bastienc/image.axd?picture=clip_image002%5B12%5D_thumb.jpg)