Blog de Bastien Chauvin

Manager Dotnet Montpellier / Passionné des technologies .Net
[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.

image

  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

clip_image002   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]

Posted: Feb 03 2010, 16:56 by bastienc | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under:
[ TechDays 2010 ] Venez me retrouvez au Techdays 2010.

Du 8 au 10 février, à Paris un évènement incontournable se déroule les Techdays. Et cette année Dotnet France va  pouvoir mettre à disposition un Stand. Nous sommes un petit groupe de Montpellier à monter, donc venez nous retrouvez sur le stand Dotnet France où serons disponible des applications WPF développées par nos stagiaires.

Vignette_Partenaire_H

A bientôt ! Et j’espère vous voir !

Posted: Jan 13 2010, 11:55 by bastienc | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under:
[ Silverlight ] Comment réaliser un snapshot de vidéo ?

     Pour le premier article de ce blog, je voulais vous faire part d’un problème rencontré sur un projet en cours ( Le site de Webcast de Dotnet France ). En effet, lors de l’upload de vidéo il nous était impossible de faire une preview de vidéo automatiquement. Nous avons donc fait un module supplémentaire en Silverlight qui va permettre de réaliser ces Snapshot qui après conversion en png seront enregistrés. Mais nous ne sommes pas au bout de nos peines. En effet nous n’avons pas recours à la classe Drawing en Silverlight, on va alors contourner ce problème.

Tout d’abord, pour cela nous allons utiliser deux classes que vous ajouterez au projet. Elles sont téléchargeables aux adresses suivantes :

- EditableImage à EditableImage.cs (4,18 kb)

- Pngencoder à PngEncoder.cs (7,50 kb)

image

    Mais pour mon exemple je vais simplement utiliser un MediaElement avec une vidéo, ainsi qu’un slider qui va me permettre de visionner pas à pas chaque image de la vidéo pour pouvoir sélectionner le bon snapshot. Et, enfin un bouton lié à son évènement click où sera situé le code principale et un contrôle image affichera le Snapschot.

Voici le code pour lier correctement notre slider et la vidéo :

 

   1:  //C#
   2:          private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
   3:          {
   4:              MediaElement.Position = TimeSpan.FromSeconds(Slider.Value *
   5:              MediaElement.NaturalDuration.TimeSpan.TotalSeconds);
   6:          }
   7:   
   8:          private void Slider_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
   9:          {
  10:              IsSliderLocked = true;
  11:              MediaElement.Pause();
  12:          }
  13:   
  14:          private void Slider_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  15:          {
  16:              IsSliderLocked = false;
  17:              MediaElement.Position = TimeSpan.FromSeconds(Slider.Value *
  18:                  MediaElement.NaturalDuration.TimeSpan.TotalSeconds);
  19:              MediaElement.Pause();
  20:          }
 

    Nous utilisons trois évènements sur le Slider. Pour une meilleure compréhension veuillez-vous référencer au code XAML mise à votre disposition à la fin de cet article.

    Maintenant dans l’évènement click du bouton nous allons utiliser la classe WriteableBitmap qui va nous permettre de faire un screen schot du Mediaelement qui sera passé en paramètre.

Ensuite nous instancions notre classe pour passer en paramètre l’objet précédent.

   1:  //C#
   2:          
   3:              WriteableBitmap wb = new WriteableBitmap(MediaElement, null);
   4:   
   5:              EditableImage imageEdit = new EditableImage(wb.PixelWidth, wb.PixelHeight);
   6:   
   7:              for (int y = 0; y < wb.PixelHeight; ++y)
   8:              {
   9:                  for (int x = 0; x < wb.PixelWidth; ++x)
  10:                  {
  11:                      int pixel = wb.Pixels[wb.PixelWidth * y + x];
  12:                      imageEdit.SetPixel(x, y,
  13:                                  (byte)((pixel >> 16) & 0xFF),
  14:                                  (byte)((pixel >> 8) & 0xFF),
  15:                                  (byte)(pixel & 0xFF),
  16:                                  (byte)((pixel >> 24) & 0xFF)
  17:                                  );
  18:                  }
  19:              }

    Les boucles vont quant à elles nous permettre de faire correspondre chaque pixel du WritableBitmap avec l’objet imageEdit. Si vous procédez à un debug pas à pas vous allez voir que nous rentrons dans nos deux classes, et que toute la conversion de l’image en tableau de byte et la conversion de chaque pixel est automatique.

   Il ne nous reste donc plus qu’à afficher cette image dans le contrôle approprié en faisant passer en paramètre à un Stream notre imageEdit et à le binder à la source de notre image par l’intermédiaire d’une BitmapImage :

 

   1:  //C#
   2:              Stream pngStream = imageData.GetStream();
   3:              BitmapImage btm = new BitmapImage();
   4:              btm.SetSource(pngStream);
   5:              SnapShot.Source = btm;

     Et le tour est joué… Voici le code XAML pour vous aider à la compréhension des nommages :

 

   1:  <--! XAML -->
   2:          
   3:  <MediaElement x:Name="MediaElement" Source="/Wildlife.wmv"/>
   4:  <Slider x:Name="Slider" Minimum="0" Maximum="1” ValueChanged="Slider_ValueChanged"
       MouseLeftButtonDown="Slider_MouseLeftButtonDown" MouseLeftButtonUp="Slider_MouseLeftButtonUp"/>
   5:  <Button Content="Take a SnapShot" Cursor="Hand" Click="SnapShot_Click"/>
   6:  <Image x:Name="SnapShot"/>
   7:   

    Maintenant c’est à vous de voir si vous voulez enregistrer cette image sur un serveur, dans une base de donnée ou encore sur l’ordinateur par l’intermédiaire d’un SaveFileDialogue . Cela pourrait éventuellement faire l’objet d’un prochain article.

Posted: Jan 07 2010, 12:25 by bastienc | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under:
[Perso] Bienvenue sur mon blog Dot-net France !

Bienvenue sur mon blog mise en ligne denrièrement. Je m'appelle CHAUVIN Bastien, en deuxième année de Supinfo à Montpellier je suis passionné des technologies .Net depuis maintenant plus d'un an. Dotnet France à était un tremplin à ma connaissance. Je vais y publier les problèmes rencontré lors de projets ou les astuces techniques découvert. Bref tout ce que je peux faire partager en ce qui concerne les technologies .net quel qu'elles soient.

Bonne Visite.

Posted: Dec 23 2009, 17:59 by bastienc | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: .NET 4.0 | Test Catégorie