0. Présentation de Microsoft Surface

0-A. Qu'est-ce que Microsoft Surface ?

Avant de se lancer dans le développement à proprement parlé, il est utile de rappeler ce qu'est Microsoft Surface.

Il s'agit d'un produit multitouche, développé par Microsoft, qui se trouve être composé de deux parties:

  • Une partie matérielle (généralement sous forme de table)
  • Une partie logicielle, qui permet l'interaction avec un (ou plusieurs) utilisateur(s)

Les utilisateurs qui manipulent la table Surface se trouvent en présence d'un écran permettant leur permettant de manipuler toute sorte de contenu digital tel que des photos, des vidéos, etc. Cependant, grâce à ces fonctionnalités techniques, cette table est bien plus qu'un simple lecteur de photos et de vidéos. Ainsi, l'utilisateur à la possibilité d'interagir avec le contenu, via un ou plusieurs doigts, pour le déplacer, l'étirer, l'agrandir, le rétrécir, etc.


Si vous voulez en savoir plus ou si vous ne connaissez pas le produit, jetez donc un coup d'oil au site officiel: http://www.microsoft.com/surface/ avant de passer à la suite de cet article qui vous expliquera comment vous pourrez développer vos propres applications pour Microsoft Surface.

0-B. Comment ca marche ?

Afin de comprendre comment une telle technologie est possible, observez l'image suivante, qui représente l'architecture de Microsoft Surface:

The architecture of the Surface development platform.  This platform includes (from bottom to top), the Windows Vista operating system, Surface Vision System, API layers for Core  or WPF, Surface Shell (which includes Launcher and Windows integration services), and Surface applications.


Comme vous pouvez le constater, plusieurs composants constituent cette plateforme:

  • Windows Vista, qui est le système d'exploitation sur lequel Surface fonctionne et qui permet de disposer d'un ensemble de fonctionnalités telles que la sécurité, la gestion des droits, etc.
  • Une couche matériel, qui contient l'ordinateur, les caméras, la surface de projection, etc. qui fonctionne sous Vista
  • Un système de vision, qui est en charge de capturer les données envoyées par le matériel, afin que vous puissiez les utiliser dans le code de votre application
  • 2 jeux d'APIs:
    • La couche WPF, qui permet l'utilisation de cette technologie et d'un ensemble de contrôle
    • La couche principale, qui permet des manipulations de l'interface graphique plus complexes que celles réalisable avec l'API WPF: animations 3D complexes, affichage via des "custom pixel shaders", etc.
  • Enfin, l'intégration entre Surface et le système d'exploitation est gérée par un shell.


Techniquement, vous pouvez donc constater qu'une table Surface n'est "rien d'autre" qu'un ordinateur équipé de Windows Vista, de matériel permettant, entre autre, la reconnaissance d'objets et d'un shell qui permet de faire la liaison entre les 2. Cependant, la partie logicielle de Surface supprime tous les éléments de l'interface, les notifications et les messages de Windows Vista.

I. Créer une première application

Pour pouvoir créer vos applications pour Microsoft Surface, il est nécessaire de disposer du SDK (Software Developement Kit) qui permet de disposer d'un émulateur, des templates de projets pour Visual Studio, etc.

Une fois le SDK installé, il est possible de lancer la création d'un nouveau projet, dans Visual Studio, via la commande "File" => "New Project":

image


Une fois le projet créé, observons le contenu de la solution:

image


Première chose à remarquer: nous retrouvons un projet contenant des fichiers XAML (Extensible Application Markup Langage). En effet, les applications Surface sont des applications WPF (Windows Presentation Foundation), comme nous allons le voir par la suite. Le projet contient différents fichiers et un répertoire:

  • App.xaml et SurfaceWindow1.xaml: Ce sont les fichiers XAML qui servent, respectivement, à définir la page de démarrage et à représenter l'interface graphique.
  • DemoAppSurface.xml: Ce fichier XML (dont le nom n'est rien d'autre que le nom du projet) contient différentes informations nécessaires pour installer l'application sur Microsoft Surface. Parmi les informations disponibles, on retrouve le nom de l'application, sa description, le nom du fichier exécutable, le nom des icones/images de l'application, etc.
 
Sélectionnez
<ss:ApplicationInfo
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:ss="http://schemas.microsoft.com/Surface/2007/ApplicationMetadata">
  <Application>
    <Title>DemoAppSurface</Title>
    <Description>DemoAppSurface</Description>
    <ExecutableFile>DemoAppSurface.exe</ExecutableFile>
    <Arguments></Arguments>
    <IconImageFile>Resources\icon.png</IconImageFile>
    <Preview>
      <PreviewImageFile>Resources\iconPreview.png</PreviewImageFile>
    </Preview>
  </Application>
</ss:ApplicationInfo>
  • Le répertoire Resource: qui contient les différents fichiers images qui seront utilisées par l'application pour diverses raisons (image d'arrière plan, icône de l'application, etc.).


Au niveau du code XAML de l'interface utilisateur, un squelette est déjà généré par le modèle de projet de Visual Studio:

 
Sélectionnez
<s:SurfaceWindow x:Class="DemoAppSurface.SurfaceWindow1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"
    Title="DemoAppSurface"
    >
  <s:SurfaceWindow.Resources>
    <ImageBrush x:Key="WindowBackground" Stretch="None" Opacity="0.6" ImageSource="pack://application:,,,/Resources/WindowBackground.jpg"/>
  </s:SurfaceWindow.Resources>

  <Grid Background="{StaticResource WindowBackground}" >

  </Grid>
</s:SurfaceWindow>


Comme vous pouvez le constater, cette interface n'a rien de bien compliquée: elle définit un objet principal de type SurfaceWindow qui contient une grille dont l'arrière plan est rempli avec une image issue des ressources de l'application. Noter cependant qu'elle définit un nouvel espace de nom, spécifique à Surface: xmlns:s="http://schemas.microsoft.com/surface/2008"

Nous allons rajouter quelques contrôles, pour commencer à prendre en main le développement. On remarque qu'il existe déjà un grand nombre de contrôles utilisables:

image


Mais, si vous ne trouvez pas votre bonheur, n'oubliez pas une chose: la technologie utilisée pour Microsoft Surface, c'est du WPF donc du .NET. Cela signifie que vous avez tout à fait la possibilité de créer votre propre contrôle en utilisant l'héritage!

Commençons par rajouter un bouton et une zone de texte:

 
Sélectionnez
<Grid Background="{StaticResource WindowBackground}" >
        <s:SurfaceButton x:Name="sBtn"
                       Content="Click Me !"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Top"
                       Click="sBtn_Click" />

        <s:SurfaceTextBox x:Name="sTb"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Height="25"
                        Width="100" />
    </Grid>


Comme vous pouvez le constater, rien de bien compliquer. Certes, nous utilisons des contrôles propres à Surface mais leurs propriétés sont les mêmes que pour des contrôles WPF classique.

Au niveau du gestionnaire d'évènements définit pour l'évènement Click, il est tout ce qu'il y a de plus simple:

 
Sélectionnez
private void sBtn_Click(object sender, RoutedEventArgs e)
{
    this.sTb.Text = this.sBtn.Content.ToString();
}


Il ne reste plus qu'à exécuter l'application. Etant donné le prix d'une table Surface (environ 15 000 $), il est sur que tout le monde ne pourra pas en acquérir une facilement. Fort heureusement, lorsque vous installer le SDK de Surface, un émulateur est également installé ce qui vous permet de tester votre application pour vous assurer qu'elle fonctionne:

image


Pour essayer votre application, il suffit de lancer l'émulateur et de faire un F5 dans Visual Studio: l'application est automatiquement déployée et lancée sur l'émulateur (de la même manière que pour les applications utilisant le Compact Framework et les émulateurs de Pocket PC/SmartPhone):

image


On constate que l'application se lance correctement et qu'il est possible de débogger avec Visual Studio:

image


On pourrait trouver bizarre qu'une zone de texte soit utilisable dans une application accessible uniquement au doigt. Fort heureusement, vous avez la possibilité d'utiliser un clavier virtuel qui apparait dès que la TextBox a le focus:

image


Pour ceux qui se poserait la question, sachez que les 4 arrondis que l'on voit dans les coins sont tout simplement les touches permettant d'accéder au menu, depuis lequel il est possible de choisir l'application à lancer/afficher.


Comme nous l'avons vu, le développement est plutôt simple à mettre en ouvre. Voyons maintenant comment utiliser un contrôle spécifique à Microsoft Surface: le contrôle ScatterView. Comme je vous l'ai indiqué précédemment, la technologie Surface permet de manipuler les contrôles insérés. Cependant, pour que cela fonctionne, il est nécessaire que les contrôles soient imbriqués dans un contrôle spécifique: le ScatterView. Nous allons légèrement modifier notre interface graphique pour y insérer ce contrôle:

 
Sélectionnez
<s:SurfaceWindow x:Class="DemoAppSurface.SurfaceWindow1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"
    Title="DemoAppSurface"
    >
  <s:SurfaceWindow.Resources>
    <ImageBrush x:Key="WindowBackground" Stretch="None" Opacity="0.6" ImageSource="pack://application:,,,/Resources/WindowBackground.jpg"/>

        <DataTemplate x:Key="svItemTemplate">
            <Image Source="{Binding}" />
         </DataTemplate>

    </s:SurfaceWindow.Resources>

    <s:ScatterView x:Name="sv"
                 Background="{StaticResource WindowBackground}"
                 ItemsSource="{Binding}"
                 ItemTemplate="{StaticResource svItemTemplate}"
                 Loaded="sv_Loaded" />
</s:SurfaceWindow>


Modifions à présent le code C# associé pour faire en sorte de charger une liste de photos, au démarrage de l'application:

 
Sélectionnez
private void sv_Loaded(object sender, RoutedEventArgs e)
{

    this.sv.DataContext = from file in Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures")
                          where file.ToLower(CultureInfo.CurrentCulture).EndsWith("jpg")
                          select file;
}


A l'exécution, la propriété DataContext est correctement affectée et chaque élément du contrôle ScatterView se voit appliqué le template définit soit, une image pointant vers l'élément indiqué:

image


Grâce à ce contrôle, il est donc possible de déplacer les images mais également de les agrandir/diminuer, de les faire pivoter, etc. De plus, le simulateur permettant d'utiliser 2 souris simultanément, il est possible de simuler l'appui de 2 doigts ou plus:

image


Bien sur, vous avez également la possibilité d'indiquer que vous ne souhaitez pas permettre à l'utilisateur de faire pivoter ou de manipuler les éléments du ScatterView. Pour cela, vous pouvez modifier les propriétés CanRotate et CanScale:

 
Sélectionnez
foreach (ScatterViewItem item in sv.Items)
{
    item.CanRotate = item.CanScale = false;
}


Comme vous pouvez le constater, le développement est relativement simple et très similaire à celui d'une application WPF. Cependant, voyons à présent comment aller un peu plus loin.

II. Allez plus loin dans le développement

II-A. Les notifications

Il est possible d'utiliser les notifications, disponibles dans Surface, pour afficher des informations qui seront présentées à l'utilisateur, éventuellement pendant une durée bien précise. Cette opération s'effectue au moyen de la méthode RequestNotification de la classe UserNotifications:

 
Sélectionnez
UserNotifications.RequestNotification("Notification", "Ce message disparaitra dans 5 secondes...", new TimeSpan(0, 0, 5));


A l'exécution, le message apparait et disparait au bout du nombre de secondes indiquées ou bien lorsque l'utilisateur clique sur la croix située au dessus du bandeau:

image

II-B. Dessiner sur Microsoft Surface

Tout comme en WPF, il existe un composant particulier, avec Surface, permettant de dessiner. Dans le cas présent, il s'agit du contrôle SurfaceInkCanvas:

 
Sélectionnez
<s:SurfaceInkCanvas x:Name="inkCanvas"
                    Grid.Row="1"
                    EditingMode="Ink" />
image


Par défaut, la couleur utilisée est le noir cependant, en accédant à la propriété DefaultDrawingAttributes, vous accédez à l'ensemble des propriétés utilisées pour afficher les différentes Strokes représentant le dessin. Vous pouvez ainsi modifier la couleur des Strokes:

 
Sélectionnez
private void ChangeInkColor(object sender, RoutedEventArgs e)
{
    var btnColor = sender as SurfaceButton;

    if (btnColor != null)
    {
        var color = btnColor.Content.ToString();

        this.inkCanvas.DefaultDrawingAttributes.Color = GetColorFromString(color);
    }
}

// Method found here: http://geekswithblogs.net/ftom/archive/2008/08/21/silverlight-2-how-to-get-a-color-or-a.aspx
private Color GetColorFromString(string colorString)
{
    Type colorType = (typeof(System.Windows.Media.Colors));
    if (colorType.GetProperty(colorString) != null)
    {
        var color = colorType.InvokeMember(colorString, BindingFlags.GetProperty, null, null, null);
        if (color != null)
        {
            return (Color)color;
        }

        throw new InvalidCastException("Color not defined");
    }

    throw new NotSupportedException();
}
image

II-C. La gestion des "Byte Tag"

Microsoft Surface possède la particularité de pouvoir reconnaitre les objets dès lors qu'ils sont posés sur la table. Pour cela, il est nécessaire d'utiliser un objet de type TagVisualizer, qui réagit à un ou plusieurs contrôles taggés qui sont posés sur la table. Le résultat du contact entre cet objet et le matériel est affiché au moyen d'un objet de type TagVisualization.

Pour définir quels sont les objets taggés qui doivent déclencher la création d'objet de type TagVisualization, il est nécessaire de passer par la propriété Definitions (qui contient un ensemble d'objet de type TagVisualizationDefinition).

Pour créer un objet de type TagVisualization, avec Visual Studio, il suffit de faire un clic droit sur votre projet puis de choisir "Add New Item" => "Surface v1.0" => "Tag Visualization (WPF)":

image


Nous allons créer un TagVisualization qui affichera un rectangle rouge lorsqu'un objet marqué sera "déposé" sur la table:

 
Sélectionnez
<s:TagVisualization x:Class="DemoAppSurface.CustomTagVisualization"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="http://schemas.microsoft.com/surface/2008"
    Loaded="CustomTagVisualization_Loaded">
    <Rectangle Fill="Red" Width="50" Height="50" />
</s:TagVisualization>

A présent, nous allons déposer notre objet TagVisualizer, qui représentera la zone sur laquelle il sera possible de déposer des objets qui seront identifiés:

 
Sélectionnez
<s:TagVisualizer Name="visualizer" 
                 Grid.Row="1"
                 HorizontalAlignment="Stretch" 
                 VerticalAlignment="Stretch">
    <s:TagVisualizer.Definitions>
        <s:ByteTagVisualizationDefinition Value="200" 
                                          TagRemovedBehavior="Fade" 
                                          Source="CustomTagVisualization.xaml"/>
    </s:TagVisualizer.Definitions>
</s:TagVisualizer>


Comme vous pouvez le constater, on place un TagVisualizer et on définit sa propriété Definitions: on y ajoute ainsi un objet de type ByteTagVisualizationDefinition qui servira à reconnaitre les objets dont le tag vaut 200 (0xc8). En effet, chaque objet associé à Microsoft Surface dispose d'un Tag, sorte d'identifiant unique, qu'il est possible de reconnaitre lorsque l'objet est déposé sur la table. Dans le cas présent, dès qu'un objet portant l'identifiant 200 est déposé sur la table, une instance du TagVisualization de type CustomTagVisualization est affiché à la place de l'objet. En ce qui concerne la propriété TagRemoveBehavior, elle sert à indiquer comment doit disparaitre le TagVisualization lorsque l'objet est enlevé de la table: sur un fondu ou directement.

A l'exécution, l'application se lance correctement et il est possible de simuler le fait qu'un objet, portant un Tag particulier, soit déposé au moyen du menu du simulateur:

image


Par défaut, le simulateur émule un objet possédant le Tag 192 (0xc0). Dès lors, si un objet portant ce Tag est déposé, rien ne se produit sur la table:

image


Cependant, si l'utilisateur dépose un objet possédant le Tag 200 (0xc8):

image


Alors une instance du TagVisualization, spécifié dans la propriété Definitions, est correctement insérée dans l'application, là où l'utilisateur l'a indiqué:

image


De plus, si vous "enlevez" l'objet qui est déposé sur la table, vous pouvez constater que l'effet de fondu (ou non) est appliqué:

image


Chaque objet de type TagVizualisationDefinition possède deux propriétés utilisées pour modifier le centre du TagVisualization affiché:

  • OrientationOffsetFromTag: qui permet de spécifier, en degré, l'inclinaison du TagVisualization
  • PhysicalCenterOffsetFromTag: qui permet de déplacer le centre du TagVisualization, en fonction d'un objet de type Vector.

Ainsi, le code suivant:

 
Sélectionnez
<s:TagVisualizer Name="visualizer" 
                 Grid.Row="1"
                 HorizontalAlignment="Stretch" 
                 VerticalAlignment="Stretch">
    <s:TagVisualizer.Definitions>
        <s:ByteTagVisualizationDefinition Value="200" 
                                          OrientationOffsetFromTag="45"
                                          PhysicalCenterOffsetFromTag="2.0,1.0"
                                          TagRemovedBehavior="Fade" 
                                          Source="CustomTagVisualization.xaml" />
    </s:TagVisualizer.Definitions>
</s:TagVisualizer>


Produit le résultat que vous pouvez constater sur cette image, où le TagVisualization est incliné de 45 degrés et déplacé de 2 sur l'axe des X et de 1 sur l'axe des Y:

image

III. Conclusion

Comme vous pouvez le constater, le développement pour Microsoft Surface est relativement simple, surtout si vous connaissez déjà le développement d'applications WPF. Certes, le prix d'une table Surface est relativement élevé mais les possibilités offertes par cette technologie sont indiscutables, dans bien des domaines: médecine, bâtiments, militaire, etc.

De plus, la mise à disposition d'un émulateur permet de tester ses applications avant de les déployer en production!

IV. Liens