VBA et développement Web

Image non disponible


précédentsommairesuivant

VII. Silverlight

SilverLight est un plugin pour internet.
Il permet de créer des applications complexes, mais aussi des pages plus simples.

Pour créer une application compilée, il faut installer un environnement de développement.
Tous les outils sont disponibles dans le Centre de développement Silverlight.
De plus, la version express de Visual Web Developper est gratuite.
Une application compilée génère un fichier XAP.
Nous n'allons pas détailler ces applications dans cet article.

Il est également possible d'écrire du code dans un fichier XAML, ce que nous allons développer.
Ce code sera interprété par le plugin Silverlight et ne nécessite rien de plus qu'un éditeur texte (et bien sûr un navigateur web pour le rendu).
Beaucoup de contrôles ne sont pas disponibles dans ce type de fichier.
Les contrôles d'un fichier XAP sont plus nombreux et complexes, mais ils ne sont pas (ou peu) exploitables en VBA.
Ils apparaissent cependant dans le plugin si on exécute le fichier XAP par exemple dans un WebBrowser.
Mais le dialogue entre VBA et les contrôles complexes du fichier XAP à travers le plugin Silverlight est très limité.

Nous allons voir quels contrôles sont disponibles en XAML dans la suite.
Ce sont des contrôles de dessin, d'affichage de texte, des images ou vidéos, et un contrôle de saisie de texte.

Consultez si besoin le forum Silverlight.

VII-A. Premier fichier XAML

Pour débuter : Tutoriel Silverlight

Créez un fichier texte avec l'extension .xaml : nommons-le silver1.xaml.
Ouvrez ce fichier avec un éditeur texte, par exemple WordPad.

Écrivez-y ce code :

 
Sélectionnez

<Canvas xmlns="http://schemas.microsoft.com/client/2007">
<Canvas>


Ce code est le minimum requis.

Le code XAML est sensible à la casse, c'est-à-dire que les minuscules et majuscules doivent être scrupuleusement respectées.


Canvas est une surface sur laquelle on va déposer nos autres contrôles : la racine du fichier est obligatoirement un canevas.
L'attribut xmlns est l'espace de noms utilisé par Silverlight.

Pour afficher le résultat, il faut créer une page HTML et y intégrer un pulgin Silverlight.

Un lien intéressant en français : Comment ajouter Silverlight à une page Web à l'aide de HTML


Créez un fichier texte avec l'extension .html : nommons-le silver1.html.
Ouvrez ce fichier avec un éditeur texte, par exemple WordPad.

Écrivez-y ce code :

 
Sélectionnez

<HTML>
<body>
   <object id="SilverLight1" data="data:application/x-silverlight," type="application/x-silverlight-2" 
    width="100&#160;%" height="100&#160;%">
     <param name="source" value="silver1.xaml"/>
      <!-- Display installation image. -->
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50303.0" 
                  style="text-decoration: none;">
         <img src="http://go.microsoft.com/fwlink/?LinkId=161376" 
               alt="Get Microsoft Silverlight" 
               style="border-style: none"/>
       </a>
   </object>
</body>
</HTML>


Ce code est du HTML classique.
On inclut dans des balises HTML, et dans le corps (body) du document, un objet Silverlight.
Cet objet a pour identifiant SilverLight1 : cet identifiant nous sera utile plus tard pour retrouver l'objet en VBA.
Les attributs data et type sont fixes quel que soit le fichier XAML utilisé.
On précise également la taille à 100 % du document. On pourrait y mettre des valeurs en pixels.

Dans l'objet, on ajoute les paramètres avec la balise param.
Le paramètre le plus important est la source qui précise où se situe le code.
Pour notre test, c'est le fichier silver1.xaml créé précédemment.
Ce fichier doit être dans le même répertoire que le fichier silver1.html, à moins de spécifier le chemin.

Au cas où le plugin n'est pas installé, il est utile d'informer l'utilisateur et de lui proposer de télécharger le plugin.
C'est le rôle du code qui suit le commentaire <!-- Display installation image. -->.
Si le plugin n'est pas installé, il s'affiche :

Image non disponible

Si le plugin est installé, la page est vide...
Pour le voir, il suffit d'afficher la page silver1.html dans un navigateur web (double-cliquez sur le fichier suffit).
Nous l'intégrerons plus tard dans un contrôle WebBrowser.

L'affichage est vide car le canevas n'a pas de dimensions (ni de couleur de fond) et on n'y a pas ajouté de contrôles.

Nous allons ajouter un texte en haut du canevas :

 
Sélectionnez

<Canvas Name="rootcanvas" xmlns="http://schemas.microsoft.com/client/2007">
    <TextBlock>Premier écran<LineBreak/>Silverlight</TextBlock>
</Canvas>


Un texte s'écrit avec la balise TextBlock.
Notez le <LineBreak/> qui définit un retour à la ligne.

Pour que les caractères accentués s'affichent correctement, le fichier doit être encodé en UTF-8.
Cet encodage peut être défini à la sauvegarde dans NotePad par exemple.

Pour écrire des caractères spéciaux : How to: Use Special Characters in XAML


Affichez la page HTML, le texte s'affiche en haut à gauche.
Il n'y a pas de couleur de fond, nous verrons par la suite pour colorer le fond.

Si rien ne s'affiche, il y a probablement une erreur : voyez le chapitre suivant.

VII-B. Gérer les erreurs

Il n'y a pas de gestion d'erreurs du code XAML par défaut.
Pour gérer les éventuelles erreurs, il faut ajouter un paramètre à l'objet SilverLight dans la page HTML.

 
Sélectionnez

     <param name="onerror" value="OnErrorEventHandler" />


On ajoute le paramètre onerror qui a la valeur OnErrorEventHandler.
OnErrorEventHandler est une fonction à définir en JavaScript.
Ajoutons cette fonction au fichier HTML à partir des instructions de cette page : Comment : ajouter Silverlight à une page Web à l'aide de HTML.

Voici donc le code de la page silver1.html :

 
Sélectionnez

<HTML>
<script type="text/javascript"> 
            
function OnErrorEventHandler(sender, errorArgs)
{
   // Create the error message to display.
   var errorMsg = "Silverlight Error: \n\n";
            
   // Specify error information common to all errors.
   errorMsg += "Error Type:    " + errorArgs.errorType + "\n";
   errorMsg += "Error Message: " + errorArgs.errorMessage + "\n";
   errorMsg += "Error Code:    " + errorArgs.errorCode + "\n";
            
   // Determine the type of error and add specific error information.
   switch(errorArgs.errorType)
   {
       case "RuntimeError":
           // Display properties specific to RuntimeErrorEventArgs.
           if (errorArgs.lineNumber != 0)
           {
               errorMsg += "Line: " + errorArgs.lineNumber + "\n";
               errorMsg += "Position: " +  errorArgs.charPosition + "\n";
           }
           errorMsg += "MethodName: " + errorArgs.methodName + "\n";
           break;
       case "ParserError":
           // Display properties specific to ParserErrorEventArgs.
           errorMsg += "Xaml File:      " + errorArgs.xamlFile      + "\n";
           errorMsg += "Xml Element:    " + errorArgs.xmlElement    + "\n";
           errorMsg += "Xml Attribute:  " + errorArgs.xmlAttribute  + "\n";
           errorMsg += "Line:           " + errorArgs.lineNumber    + "\n";
           errorMsg += "Position:       " + errorArgs.charPosition  + "\n";
           break;
       default:
           break;
   }
   // Display the error message.
   alert(errorMsg);
}
            
</script>
            
<body>
   <object id="SilverLight1" data="data:application/x-silverlight," type="application/x-silverlight-2" 
    width="100&#160;%" height="100&#160;%">
     <param name="source" value="silver1.xaml"/>
     <param name="onerror" value="OnErrorEventHandler" />
     <param name="onresize" value="OnResizeEventHandler" />
      <!-- Display installation image. -->
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50303.0" 
                  style="text-decoration: none;">
         <img src="http://go.microsoft.com/fwlink/?LinkId=161376" 
               alt="Get Microsoft Silverlight" 
               style="border-style: none"/>
       </a>
   </object>
</body>
</HTML>


En cas d'erreur, le script affiche une boîte de message.

VII-C. Contrôles disponibles

Les contrôles, ainsi que leurs méthodes et propriétés disponibles, sont répertoriés sur cette page : JavaScript API for Silverlight.
Descendez dans la page jusqu'à Documentation for the JavaScript API.
Les contrôles sont présents (aux côtés d'autres objets) dans Objects Reference.

Nous allons utiliser dans la suite quelques-uns de ces contrôles.

VII-D. Adapater le canevas à la taille de la page

Tout d'abord nous avons remarqué qu'il n'y a pas de fond à la page Silverlight.
Effectivement le canevas a été défini sans taille ni couleur de fond.
Il n'est pas nécessaire de préciser une taille au canevas qui ne sert dans ce cas qu'à positionner les éléments.
Les éléments qui "débordent" du canevas sont quand même affichés.

Deux solutions pour ajouter une couleur de fond :
1 - soit ajouter un paramètre background à l'objet Silverlight de la page HTML.

 
Sélectionnez

    <param name="background" value="yellow" />


Vous pouvez trouver les couleurs prédéfinies et le codage hexa des couleurs personnalisées par exemple ici : Color Table ;

2 - soit définir une couleur et une taille au canevas dans le fichier XAML :

 
Sélectionnez

<Canvas Width="300" Height="300" Background="#50FFFF00" xmlns="http://schemas.microsoft.com/client/2007">


J'ai ici défini une taille de 300x300 pixels, et une couleur de fond jaune (rouge+vert) de canal alpha (transparence) 50.

Retrouvez les couleurs prédéfinies et le codage hexa des couleurs personnalisées : Color, structure.

L'écran affiche la couleur de fond uniquement sur la taille du canevas. Le reste est la couleur de fond de la page internet.

Pour redimensionner le canevas à la taille de la page internet, nous allons écrire une petite fonction JavaScript.
Cette fonction sera appelée par le paramètre onresize de l'objet Silverlight dans la page HTML.
Ajoutez ce paramètre sous le paramètre "source".

 
Sélectionnez

     <param name="onresize" value="OnResizeEventHandler" />


Écrivons ensuite, toujours dans la page silver1.html, la fonction JavaScript :

 
Sélectionnez

<HTML>
<script type="text/javascript"> 
            
function OnErrorEventHandler(sender, errorArgs)
{
[...]
}
            
function OnResizeEventHandler(sender, args)
{
    sender.width = sender.gethost().content.actualwidth;
    sender.height = sender.gethost().content.actualheight;
}
            
</script>
            


La fonction OnResizeEventHandler est à ajouter après la fonction OnErrorEventHandler, juste avant la balise de fin </script>.
Elle est assez simple :
- sender est le canevas racine de l'objet Silverlight ;
- gethost permet de remonter au plugin Silverlight : ne pas oublier les parenthèses pour indiquer que c'est une méthode ;
- On récupère alors la taille de l'objet et on l'affecte au canevas.

Pour que tout cela fonctionne, il faut que notre canevas soit nommé "rootcanvas" dans le fichier silver1.xaml :

 
Sélectionnez

<Canvas Name="rootcanvas" Background="#50FFFF00" xmlns="http://schemas.microsoft.com/client/2007">


Pas besoin de définir de dimensions ici, elles seront définies par JavaScript.

Pour parfaire le tout, on peut modifier les marges du corps du document HTML afin qu'il n'y ait plus d'entourage blanc.

 
Sélectionnez

<body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">


Si vous affichez la page silver1.html, vous obtenez le texte sur fond jaune qui remplit toute la page, même lorsqu'on redimensionne le navigateur.
En effet, l'objet Silverlight est défini avec des dimensions à 100 % : si on redimensionne le navigateur, l'objet Silverlight est redimensionné également.

Pour résumer, voici le code du fichier silver1.xaml :

 
Sélectionnez

<Canvas Name="rootcanvas" Background="#50FFFF00" xmlns="http://schemas.microsoft.com/client/2007"> 
    <TextBlock>Premier écran<LineBreak/>Silverlight</TextBlock>
</Canvas>


Et voici le code du fichier silver1.html :

 
Sélectionnez

<HTML>
<script type="text/javascript"> 
            
function OnErrorEventHandler(sender, errorArgs)
{
   // Create the error message to display.
   var errorMsg = "Silverlight Error: \n\n";
            
   // Specify error information common to all errors.
   errorMsg += "Error Type:    " + errorArgs.errorType + "\n";
   errorMsg += "Error Message: " + errorArgs.errorMessage + "\n";
   errorMsg += "Error Code:    " + errorArgs.errorCode + "\n";
            
   // Determine the type of error and add specific error information.
   switch(errorArgs.errorType)
   {
       case "RuntimeError":
           // Display properties specific to RuntimeErrorEventArgs.
           if (errorArgs.lineNumber != 0)
           {
               errorMsg += "Line: " + errorArgs.lineNumber + "\n";
               errorMsg += "Position: " +  errorArgs.charPosition + "\n";
           }
           errorMsg += "MethodName: " + errorArgs.methodName + "\n";
           break;
       case "ParserError":
           // Display properties specific to ParserErrorEventArgs.
           errorMsg += "Xaml File:      " + errorArgs.xamlFile      + "\n";
           errorMsg += "Xml Element:    " + errorArgs.xmlElement    + "\n";
           errorMsg += "Xml Attribute:  " + errorArgs.xmlAttribute  + "\n";
           errorMsg += "Line:           " + errorArgs.lineNumber    + "\n";
           errorMsg += "Position:       " + errorArgs.charPosition  + "\n";
           break;
       default:
           break;
   }
   // Display the error message.
   alert(errorMsg);
}
            
function OnResizeEventHandler(sender, args)
{
    sender.width = sender.gethost().content.actualwidth;
    sender.height = sender.gethost().content.actualheight;
}
</script>
            
<body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">
   <object id="SilverLight1" data="data:application/x-silverlight," type="application/x-silverlight-2" 
    width="100%" height="100%">
     <param name="source" value="silver1.xaml"/>
     <param name="onerror" value="OnErrorEventHandler" />
     <param name="onresize" value="OnResizeEventHandler" />
      <!-- Display installation image. -->
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50303.0" 
                  style="text-decoration: none;">
         <img src="http://go.microsoft.com/fwlink/?LinkId=161376" 
               alt="Get Microsoft Silverlight" 
               style="border-style: none"/>
       </a>
   </object>
</body>
</HTML>


Cette page HTML est réutilisable à loisir : il suffit de modifier la source de l'objet Silverlight1.
Il faut bien sûr nommer le canevas "rootcanvas" pour que la fonction de redimensionnement fonctionne.

VII-E. Arranger les contrôles dans une grille

Cela ne vous a pas échappé, le texte n'est pas centré...
Pour le centrer, c'est plus compliqué qu'on pourrait l'imaginer.

Il y a bien une propriété TextAlignement :

 
Sélectionnez

<Canvas Name="rootcanvas" Background="#50FFFF00" xmlns="http://schemas.microsoft.com/client/2007">
    <TextBlock TextAlignment="Center">
        Premier écran<LineBreak/>Silverlight
    </TextBlock>
</Canvas>


Mais voici le résultat :

Image non disponible

Le texte n'est pas centré sur le canevas, mais seulement sur sa plus grande ligne.
En effet, le texte est centré sur sa largeur, et sa largeur est déterminée lors de l'écriture du texte.
On voudrait définir sa largeur en fonction de celle du canevas qui le contient, mais on ne peut pas (du moins je ne sais pas).

C'est le contrôle Grid qui va nous sauver.
Nous allons créer une grille d'une seule colonne et de deux lignes.
La première ligne contiendra le texte de titre, et la deuxième ligne un canevas sur lequel nous poursuivrons.
Là où la grille nous sauve, c'est que les éléments que l'on place dans les cellules d'une grille occupent toute la cellule.
On dimensionnera bien sûr la grille pour qu'elle occupe toute la page, un peu comme nous l'avons fait avec le canevas.

Voici le nouveau code du fichier silver1.xaml :

 
Sélectionnez

<Canvas Name="rootcanvas" Background="#50FFFF00" xmlns="http://schemas.microsoft.com/client/2007"> 
<!-- La Grille -->
<Grid Name="rootgrid" ShowGridLines="True">
    <!-- Définition des colonnes -->
    <Grid.ColumnDefinitions>
           <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <!-- Définition des lignes -->
    <Grid.RowDefinitions>
           <RowDefinition Height="Auto" />
           <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <!-- Texte d'en-tête dans la première ligne -->
    <TextBlock Grid.Row="0" Grid.Column="0" TextAlignment="Center">
           Premier écran<LineBreak/>Silverlight
       </TextBlock>
    <!-- Canvas dans la deuxième ligne -->
    <Canvas Name="secondcanvas" Background="#FFDDDD" Grid.Row="1" Grid.Column="0">
        <!-- On ajoute d'autres contrôles ici -->
    </Canvas>
</Grid>
</Canvas>


Nous avons nommé la grille rootgrid afin de la retrouver facilement par code.
Pour y voir plus clair, on affiche les lignes de la grille avec ShowGridLines="True".

Ensuite on définit les colonnes :
- il n'y a qu'une colonne : le * en largeur (Width) signifie que la colonne prend tout l'espace disponible.

Puis on définit les lignes :
- Première ligne pour l'en-tête : on ne définit pas de hauteur (Height) particulière, "Auto" signifie que la ligne prendra la taille de l'élément qu'elle contient.
Elle s'adaptera donc au texte que nous écrirons dedans.
- Deuxième ligne : le * en hauteur (Height) signifie que la ligne prend tout l'espace restant.

Et enfin on place nos éléments.
Pour chaque élément, il faut préciser la colonne et la ligne dans lesquelles on les place.
La première ligne et la première colonne commencent à l'indice 0.

Dans la première ligne on place notre texte centré.
Dans la deuxième ligne on place un canevas dans lequel on pourra mettre d'autres éléments.
Pour distinguer visuellement ce deuxième canevas, on a défini une couleur différente.

La grille ne va pas par défaut occuper toute la taille du canevas qui la contient.
On va la redimensionner dans la fonction JavaScript OnResizeEventHandler du fichier silver1.html.

 
Sélectionnez

function OnResizeEventHandler(sender, args)
{
    sender.width = sender.gethost().content.actualwidth;
    sender.height = sender.gethost().content.actualheight;
    sender.findname("rootgrid").width = sender.gethost().content.actualwidth;
    sender.findname("rootgrid").height = sender.gethost().content.actualheight;
}


Après avoir redimensionné le canevas racine, on redimensionne la grille nommée rootgrid.
Pour retrouver la grille, appelez FindName sur le sender (notre canevas).

Voici le résultat obtenu :

Image non disponible

Le texte est enfin centré.
On voit bien en rose le deuxième canevas qui occupe toute sa cellule.
Si on redimensionne le navigateur, tout le contenu est redimensionné.

À noter : les lignes de la grille ne sont disponibles qu'en pointillés. Cela est prévu à des fins de débogage uniquement.
Pour utiliser d'autres types de traits, il faut mettre chacun des éléments dans un élément Border.
Par exemple, pour encadrer le deuxième canevas d'un trait bleu de deux pixels d'épaisseur :

 
Sélectionnez

    <!-- Canevas dans la deuxième ligne -->
    <Border BorderThickness="2" BorderBrush="Blue" Grid.Row="1" Grid.Column="0">
        <Canvas Name="secondcanvas" Background="#FFDDDD">
            <!-- On ajoute d'autres contrôles ici -->
        </Canvas>
    </Border>


C'est alors l'élément Border qui est positionné dans la grille. Il contient l'élément Canvas.

Un rappel des codes complets des fichiers avant de se lancer enfin avec VBA :

- le fichier sliver1.xaml :

 
Sélectionnez

<Canvas Name="rootcanvas" Background="#50FFFF00" xmlns="http://schemas.microsoft.com/client/2007"> 
<!-- La Grille -->
<Grid Name="rootgrid" ShowGridLines="False">
    <!-- Définition des colonnes -->
    <Grid.ColumnDefinitions>
           <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <!-- Définition des lignes -->
    <Grid.RowDefinitions>
           <RowDefinition Height="Auto" />
           <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <!-- Texte d'en-tête dans la première ligne -->
    <TextBlock Grid.Row="0" Grid.Column="0" TextAlignment="Center">
           Premier écran<LineBreak/>Silverlight
       </TextBlock>
    <!-- Canevas dans la deuxième ligne -->
    <Border BorderThickness="2" BorderBrush="Blue" Grid.Row="1" Grid.Column="0">
        <Canvas Name="secondcanvas" Background="#FFDDDD">
            <!-- On ajoute d'autres contrôles ici -->
        </Canvas>
    </Border>
</Grid>
</Canvas>


- le fichier sliver1.html :

 
Sélectionnez

<HTML>
<script type="text/javascript"> 
            
function OnErrorEventHandler(sender, errorArgs)
{
   // Create the error message to display.
   var errorMsg = "Silverlight Error: \n\n";
            
   // Specify error information common to all errors.
   errorMsg += "Error Type:    " + errorArgs.errorType + "\n";
   errorMsg += "Error Message: " + errorArgs.errorMessage + "\n";
   errorMsg += "Error Code:    " + errorArgs.errorCode + "\n";
            
   // Determine the type of error and add specific error information.
   switch(errorArgs.errorType)
   {
       case "RuntimeError":
           // Display properties specific to RuntimeErrorEventArgs.
           if (errorArgs.lineNumber != 0)
           {
               errorMsg += "Line: " + errorArgs.lineNumber + "\n";
               errorMsg += "Position: " +  errorArgs.charPosition + "\n";
           }
           errorMsg += "MethodName: " + errorArgs.methodName + "\n";
           break;
       case "ParserError":
           // Display properties specific to ParserErrorEventArgs.
           errorMsg += "Xaml File:      " + errorArgs.xamlFile      + "\n";
           errorMsg += "Xml Element:    " + errorArgs.xmlElement    + "\n";
           errorMsg += "Xml Attribute:  " + errorArgs.xmlAttribute  + "\n";
           errorMsg += "Line:           " + errorArgs.lineNumber    + "\n";
           errorMsg += "Position:       " + errorArgs.charPosition  + "\n";
           break;
       default:
           break;
   }
   // Display the error message.
   alert(errorMsg);
}
            
function OnResizeEventHandler(sender, args)
{
    sender.width = sender.gethost().content.actualwidth;
    sender.height = sender.gethost().content.actualheight;
    sender.findname("rootgrid").width = sender.gethost().content.actualwidth;
    sender.findname("rootgrid").height = sender.gethost().content.actualheight;
}
            
</script>
<body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">
   <object id="SilverLight1" data="data:application/x-silverlight," type="application/x-silverlight-2" 
    width="100%" height="100%">
     <param name="source" value="silver1.xaml"/>
    <param name="onerror" value="OnErrorEventHandler" />
    <param name="onresize" value="OnResizeEventHandler" />
      <!-- Display installation image. -->
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50303.0" 
                  style="text-decoration: none;">
         <img src="http://go.microsoft.com/fwlink/?LinkId=161376" 
               alt="Get Microsoft Silverlight" 
               style="border-style: none"/>
       </a>
   </object>
</body>
</HTML>

VII-F. Intégrer la page SilverLight dans un WebBrowser

Pour ajouter un Webbrowser à un formulaire, je vous renvoie vers le chapitre III-B Intégrer un navigateur internet à l'application.

Il suffit à l'ouverture du formulaire de naviguer vers notre page sliver1.html

 
Sélectionnez

Me.ctlNav.Navigate "C:\silver1.html"


Il faut préciser le chemin complet du fichier HTML.

Pour trouver le chemin de votre application, utilisez une de ces fonctions :

Application Fonction
Access CurrentProject.Path
Excel ThisWorkbook.Path
Word ThisDocument.Path
PowerPoint ThisPresentation.Path

Pour Access, n'oubliez d'ajouter Object avant le navigate.

VII-G. Piloter la page SilverLight à partir de VBA

Nous allons dans ce chapitre utiliser VBA pour gérer l'objet Silverlight.

Silverlight n'étant pas du tout prévu pour VBA, cela ne va pas être si facile.

VII-G-1. La librairie AgControl Type Library

Nous pourrions être tentés d'utiliser une librairie.
Il y en a bien une : AgControl Type Library.

Si on la référence, on voit ensuite dans l'explorateur d'objet (F2) les classes de cette librairie (nommée XcpControlLib) :

Image non disponible

Il n'y a en fait pas grand-chose à notre disposition.

- IXcpControl est l'interface pour l'objet Plugin.
- IXcpObject est l'interface pour un élément contenu dans le Plugin.
- Xcpcontrol est un objet d'automation (j'avoue : je ne sais pas à quoi il sert).

Il est intéressant de voir les propriétés et méthodes disponibles, mais les éléments IXcpObject ne possèdent même pas de propriétés.
Nous n'allons en fait même pas utiliser cette librairie peu utile.
De plus, si nous référençons une version 4.0 de cette librairie par exemple, l'application ne fonctionnera pas sur un poste équipé seulement de la version 3 de Silverlight.
Nous utiliserons des objets non typés, et cela nous facilitera en fait la tâche.
Sinon, comment appeler une méthode d'un objet IXcpObject si rien n'est disponible : on aurait un message d'erreur alors que des méthodes existent pour ces éléments.

VII-G-2. Atteindre le plugin Silverlight

On va chercher le plugin une fois la page chargée : dans l'événement DocumentComplete du navigateur.
Recherchez cet événement dans les listes déroulantes en haut du module de code du formulaire.

 
Sélectionnez

Private Sub ctlNav_DocumentComplete(ByVal pDisp As Object, URL As Variant)
            
End Sub


- pDisp est l'objet WebBrowser.
- URL est l'adresse du document HTML.

Le plugin est un élément HTML. Il est possible de le retrouver dans le document (HTMLDocument) avec fonction getElementById.
Nous avons vu cette fonction au chapitre IV.

L'objet plugin nous sera utile à plusieurs endroits du code.
Nous ajoutons donc une déclaration en en-tête du module du formulaire.

 
Sélectionnez

Private oSL As Object


Comme expliqué au chapitre précédent, oSL n'a pas de type particulier. Ce sera en fait un XcpControl.

Une fois le document chargé, on récupère l'objet plugin :

 
Sélectionnez

Private Sub ctlNav_DocumentComplete(ByVal pDisp As Object, URL As Variant)
Set oSL = pDisp.Document.getElementById("silverlight1").Object
End Sub


silverlight1 est l'id de notre objet dans le fichier silver1.html.
On rajoute Object à la fin car getElementById renvoie un élément HTML qui contient le plugin dans cette propriété Object.

On le voit bien dans la fenêtre Variables locales, avec un point d'arrêt dans l'événement DocumentComplete :

Image non disponible

- pDisp est un WebBrowser.
- Document est un HTMLDocument.
- le sixième élément est un HTMLObjectElement, on le récupère avec getElementById.
- object est un IXcpControl2.

On retrouve sur cet objet la source ("silver1.xaml") et la gestion d'erreur ("OnErrorEventHandler").

On remarque une propriété importante : IsLoaded.
Cette propriété vaut True lorsque le plugin est chargé.

VII-G-3. Lire la page Silverlight

On a donc récupéré un objet oSL.
Dans DocumentComplete, cet objet n'est pas encore chargé.

Si on place une boîte de message, on le voit bien :

 
Sélectionnez

Private Sub ctlNav_DocumentComplete(ByVal pDisp As Object, URL As Variant)
Set oSL = pDisp.Document.getElementById("silverlight1").Object
MsgBox oSL.IsLoaded
End Sub


La boîte de message indique "Faux"...
Si on veut lire le contenu du plugin, il faut d'abord attendre qu'il soit chargé :

 
Sélectionnez

Private Sub ctlNav_DocumentComplete(ByVal pDisp As Object, URL As Variant)
Set oSL = pDisp.Document.getElementById("silverlight1").Object
While Not oSL.IsLoaded
   DoEvents ' indispensable pour ne pas tout bloquer
Wend
MsgBox oSL.IsLoaded
End Sub       


La boîte de message indique "Vrai"... Le plugin est chargé.

Le contenu du plugin se trouve dans l'objet content dont vous trouverez les méthodes et propriétés ici : Silverlight Plug-in.

Les propriétés de cet objet ne sont pas directement accessibles en VBA.
Par exemple :

 
Sélectionnez

MsgBox oSL.Content.ActualWidth


Renvoie une erreur : Utilisation incorrecte de Null.
Pour lire une propriété, il faut utiliser l'instruction CallByName :

 
Sélectionnez

MsgBox CallByName(oSL.Content, "ActualWidth", VbGet)


La boîte de message affiche alors la largeur en pixels.

On souhaite maintenant récupérer l'élément racine, c'est-à-dire le canevas nommé "rootcanvas".

 
Sélectionnez

dim oRoot as object 
set oRoot = CallByName(oSL.Content, "root", VbGet)


oRoot est alors un objet de type Canvas.

Pour rappel, les méthodes et propriétés des objets sont ici JavaScript API for Silverlight.


Pour afficher le nom de l'élément ("rootcanvas"), il suffit d'appeler sa propriété Name :

 
Sélectionnez

MsgBox CallByName(oRoot, "Name", VbGet)


Pour de nombreux objets, on a des méthodes GetValue et SetValue qui sont plus simples que CallByName :

 
Sélectionnez

MsgBox oRoot.getvalue("Name")


Si vous souhaitez connaître le type d'un objet, appelez la méthode toString :

 
Sélectionnez

MsgBox oRoot.toString


Pour la racine toString renvoie Canvas.
On peut aussi, en débogage, survoler l'objet oRoot. L'info-bulle nous indique la même information.

Maintenant pour obtenir les éléments contenus dans ce canevas, utilisez la propriété Children.
Chidren renvoie une collection.
On peut récupérer le nombre d'éléments avec Count.
GetItem permet alors de récupérer un élément par son indice (débute à 0).

Si vous utilisez une variable, il sera peut-être nécessaire de convertir l'indice en entier avec CInt.

 
Sélectionnez

Dim oRoot As Object
Dim oChildren As Object
Set oRoot = CallByName(oSL.Content, "root", VbGet)
Set oChildren = oRoot.getvalue("Children")
MsgBox "Nombre d'éléments dans le canevas racine : " & oChildren.getvalue("Count")
MsgBox "Nom du premier élément : " & oChildren.GetItem(0).getvalue("Name")


Il n'y a qu'un élément dans le canevas racine, c'est la grille "rootgrid".

On peut parcourir ainsi le contenu niveau par niveau.
Un exemple avec With :

 
Sélectionnez

' recherche la racine du plugin = canevas rootcanvas
With CallByName(oSL.Content, "root", VbGet)
   ' obtient la collection d'éléments du canevas
   With .getvalue("children")
       ' Premier élément = rootgrid
       With .GetItem(0)
           ' obtient la collection d'éléments de la grille
           With .getvalue("children")
               ' Deuxième élément de la grille = border
               With .GetItem(1)
                   ' Element du border (il n'y en a qu'un)
                   With .getvalue("child")
                           ' C'est le canevas secondcanvas
                           MsgBox .getvalue("name")
                   End With
               End With
           End With
       End With
   End With
End With


Si l'élément est nommé, on peut y accéder directement avec findName :

 
Sélectionnez

With oSL.Content.findName("secondcanvas")
   MsgBox .getvalue("ActualWidth")
End With


findName peut également être utilisé sur un élément pour rechercher à l'intérieur de celui-ci.

VII-G-4. Modifier la page Silverlight

Nous allons modifier le titre de la page.
Pour nous faciliter la tâche, nommons le TextBlock qui contient le titre dans le fichier silver1.xaml :

 
Sélectionnez

    <!-- Texte d'en-tête dans la première ligne -->
    <TextBlock Name="titre" Grid.Row="0" Grid.Column="0" TextAlignment="Center">
           Premier écran<LineBreak/>Silverlight
       </TextBlock>


On peut ainsi le retrouver facilement avec findName.

 
Sélectionnez

Dim oTitre As Object
Set oTitre = oSL.Content.findName("titre")


Pour modifier une propriété, c'est facile. Il suffit d'utiliser SetValue :

 
Sélectionnez

oTitre.SetValue "text", "Mon Nouveau Titre"
oTitre.SetValue "Foreground", "red"
oTitre.SetValue "FontSize", 24


Le texte du titre est alors modifié, en rouge, et de taille 24 pixels.

VII-G-5. Ajouter dynamiquement un élément à la page Silverlight

Nous allons ici voir comment ajouter un élément à la page déjà chargée.
On continue avec les mêmes fichiers silver1.html et silver1.xaml.

Le fichier HTML est chargé dans un WebBrowser comme vu précédemment.
Et on attend dans DocumentComplete le chargement du plugin :

 
Sélectionnez

Private Sub ctlNav_DocumentComplete(ByVal pDisp As Object, URL As Variant)
Set oSL = pDisp.Document.getElementById("silverlight1").Object
While Not oSL.IsLoaded
   DoEvents ' indispensable pour ne pas tout bloquer
Wend
' On écrira la suite du code ici
End Sub       


On souhaite ajouter en VBA un texte au canevas "secondcanvas".
Commençons par écrire le code XAML de l'élément à ajouter.
On ajoute un simple TextBlock :

 
Sélectionnez

Dim sxaml As String
sxaml = "<TextBlock>Texte ajouté</TextBlock>"


Pour créer un élément, il faut utiliser la méthode CreateFromXaml de l'objet Content du plugin.
On aurait aimé pouvoir écrire :

 
Sélectionnez

set oElement = oSL.Content.CreateFromXAML(sxaml)


Mais ce code provoque une erreur.
La seule solution que j'ai trouvée est de faire la création de l'élément en JavaScript.
Voici une petite fonction à ajouter dans la balise script du fichier silver1.html.

 
Sélectionnez

function AddElement(sxaml,sobject,sname,position) {
        // objet plugin
        var plugin = document.getElementById(sobject);
        // création du nouvel élément
        var element = plugin.content.CreateFromXaml(sxaml);
        // Ajout de l'élément
        if (position==-1)
        // Ajout à la fin
        {    plugin.content.FindName(sname).children.add (element);    }
        else
        // Ajout avec position
        {    plugin.content.FindName(sname).children.insert (position,element);    }
            
        }


Cette fonction demande en paramètres :
- sxaml : le code XAML de l'élément à ajouter.
- sobject : le nom de l'objet Silverlight (Silverlight1 pour notre exemple).
- sname : le nom de l'objet dans lequel on ajoute l'élément.
- position : la position à laquelle ajouter l'élément. La position commence à l'indice 0, on utilise -1 pour ne pas indiquer de position.

La méthode add de la collection children ajoute un élément à la fin.
La méthode insert insère un élément à une position donnée.

Cette fonction peut être appelée en VBA ainsi :

 
Sélectionnez

pDisp.Document.parentWindow.execscript "AddElement('" & sxaml & "','SilverLight1','secondcanvas',-1)"


La méthode execscript de la fenêtre (parentWindow) du document permet d'exécuter du JavaScript.
La limitation est que tout doit être écrit dans une seule chaîne de caractères, y compris les paramètres.
C'est pour cela que les paramètres ne sont pas des objets (ce qui nous aurait simplifier la tâche).
Notez que execscript ne retourne pas de valeur.

Les chaînes de caractères sont encadrées par des simples quotes (').
Pour inclure ce caractère dans le XAML, utilisez "\'". Par exemple :

 
Sélectionnez

sxaml = "<TextBlock>J\'ajoute un texte</TextBlock>"


Les sauts de ligne (vbCrLf) provoquent également une erreur.
Il est souvent plus facile de créer d'abord l'élément puis de mettre à jour ses propriétés :

 
Sélectionnez

Dim sxaml As String
sxaml = "<TextBlock/>"
pDisp.Document.parentWindow.execscript "AddElement('" & sxaml & "','SilverLight1','secondcanvas',-1)"
With oSL.content.findname("secondcanvas").getvalue("Children").getitem(0)
   .SetValue "text", "J'ajoute du texte" & vbCrLf & "avec un saut de ligne"
End With


De cette manière, pas de problème pour ajouter des quotes (') ou des sauts de ligne (vbCrLf).

Pour nous faciliter la tâche, on peut créer une fonction VBA :

 
Sélectionnez

'------------------------------------------------------------------------------
' Insère un élément dans silverlight
'------------------------------------------------------------------------------
' pxaml : code XAML : ex. : "<TextBlock>J\'ajoute un texte</TextBlock>"
' pDocument : un document HTML
' pObjet : l'Id de l'objet Silverlight dans le document HTML
' pElement : le nom de l'élément parent
' pPosition : position optionnelle de l'élément
'------------------------------------------------------------------------------
Public Function SLInsertElement(ByVal pxaml As String, pDocument As Object, pObject As String, _
                                pElement As String, Optional pPosition As Long = -1)
Dim sScript As String
sScript = "var plugin = document.getElementById('" & pObject & "');" & vbCrLf & _
         "var element = plugin.content.CreateFromXaml('" & pxaml & "');" & vbCrLf
If pPosition = -1 Then
   sScript = sScript & "plugin.content.FindName('" & pElement & "').children.add (element);"
Else
   sScript = sScript & "plugin.content.FindName('" & pElement & "').children.insert  (element," & pPosition & ");"
End If
pDocument.parentWindow.execscript sScript
End Function


Cette fonction génère le code JavaScript nécessaire et l'exécute.
La fonction AddElement n'est plus utile dans le JavaScript du fichier silver1.html.

On pourra alors écrire :

 
Sélectionnez

SLInsertElement "<TextBlock>J\'ajoute un texte</TextBlock>", pDisp.Document, "SilverLight1", "secondcanvas"
SLInsertElement "<TextBlock Canvas.Top=""15"">Et un deuxième</TextBlock>", pDisp.Document, "SilverLight1", "secondcanvas"


On a ici ajouté deux textes.
Par défaut les éléments sont positionnés à l'origine du parent, en haut à gauche.
Pour les positionner, il faut utiliser les attributs Canvas.Top et Canvas.Left.
Bien ajouter Canvas, Top tout seul ne fonctionne pas.
Par contre, pour la taille, c'est Width et Height (sans le préfixe Canvas).

VII-H. Gérer les événements de la page SilverLight à partir de VBA

VII-H-1. Saisie de texte

Commençons par ajouter à notre fichier xaml deux zones de saisie de texte :

 
Sélectionnez

<Canvas Name="rootcanvas" Background="#50FFFF00" xmlns="http://schemas.microsoft.com/client/2007"> 
<!-- La Grille -->
<Grid Name="rootgrid" ShowGridLines="False">
    <!-- Définition des colonnes -->
    <Grid.ColumnDefinitions>
           <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <!-- Définition des lignes -->
    <Grid.RowDefinitions>
           <RowDefinition Height="Auto" />
           <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <!-- Texte d'en-tête dans la première ligne -->
    <TextBlock Name="titre" Grid.Row="0" Grid.Column="0" TextAlignment="Center">
           Premier écran<LineBreak/>Silverlight
       </TextBlock>
    <!-- Canevas dans la deuxième ligne -->
    <Border BorderThickness="2" BorderBrush="Blue" Grid.Row="1" Grid.Column="0">
        <Canvas Name="secondcanvas" Background="#FFDDDD">
            <TextBlock>Utilisateur :</TextBlock>
            <TextBox Canvas.Left="120" Name="Login"/>
            <TextBlock Canvas.Top="40">Mot de passe :</TextBlock>
            <PasswordBox Canvas.Left="120" Canvas.Top="40" Name="Password"/>
        </Canvas>
    </Border>
</Grid>
</Canvas>


Le contrôle TextBox permet de saisir du texte.
Le contrôle PasswordBox permet de saisir du texte masqué (pour un mot de passe donc).

Image non disponible

Par défaut les contrôles de saisie font (à peu près) 1 caractère de large et s'étendent durant la saisie.

Pour éviter ceci ,il suffit d'ajouter un attribut de taille (Width) aux éléments :

 
Sélectionnez

            <TextBlock>Utilisateur :</TextBlock>
            <TextBox Width="200" Canvas.Left="120" Name="Login"/>
            <TextBlock Canvas.Top="40">Mot de passe :</TextBlock>
            <PasswordBox Width="200" Canvas.Left="120" Canvas.Top="40" Name="Password"/>


Maintenant nous allons réagir à la saisie.
Pour capturer un événement d'un élément Silverlight, il faut créer un gestionnaire d'événements.
Nous avons déjà créé des gestionnaires d'événements aux chapitres IV-E et V-D-2.
C'est pour Silverlight la même procédure, il faut un objet ayant une méthode par défaut.
Créez un module de classe :

 
Sélectionnez

Option Explicit
            
Public Event SLEvent(sender As Variant, args As Variant)
            
Public Sub EventFromSL(sender As Variant, args As Variant)
'Attribute EventFromSL.VB_UserMemId = 0
   RaiseEvent SLEvent(sender, args)
End Sub


Sauvegardez-le sous le nom clEventsSL.
Puis exportez ce module, supprimez-le et décommentez la ligne 'Attribute ... du fichier exporté avant de le réimporter.
EventFromSL est alors la méthode par défaut de cette classe.

Pour une utilisation dans une application Internet Explorer, il faut que ce module soit public.
Définissez la propriété Instancing du module à 2 - PublicNotCreatable.
Le module peut rester privé si la page est affichée dans un contrôle WebBrowser.

Pour utiliser cet objet, il faut d'abord le déclarer en en-tête de module avec WithEvents :

 
Sélectionnez

Private WithEvents oEventsTextChanged As clEventsSL


Puis instanciez l'objet à l'ouverture du formulaire par exemple :

 
Sélectionnez

Set oEventsTextChanged = New clEventsSL


Ce qui donne pour le code d'un userForm dans Excel :

 
Sélectionnez

Option Explicit
            
Private oSL As Object
Private WithEvents oEventsTextChanged As clEventsSL
            
Private Sub UserForm_Initialize()
Set oEventsTextChanged = New clEventsSL
Me.ctlNav.Navigate ThisWorkbook.Path & "/silver1.html"
End Sub
            
Private Sub ctlNav_DocumentComplete(ByVal pDisp As Object, URL As Variant)
Set oSL = pDisp.Document.getElementById("silverlight1").Object
While Not oSL.IsLoaded
   DoEvents ' indispensable pour ne pas tout bloquer
Wend
End Sub


Maintenant il faut affecter ce gestionnaire d'événements aux éléments, sur le ou les événements désirés.
Cela se fait avec la méthode AddEventListener :

 
Sélectionnez

' TextBox : http://msdn.microsoft.com/en-us/library/cc917833(v=VS.95).aspx
oSL.content.findname("Login").addeventlistener "TextChanged", oEvents
' PasswordBox : http://msdn.microsoft.com/en-us/library/cc917814(v=VS.95).aspx
oSL.content.findname("Password").addeventlistener "PasswordChanged", oEvents


En commentaire dans le code, il y a les liens vers les pages MSDN où trouver les noms d'événements.
On a choisi, pour tester, les événements de changement de texte.

Créez enfin la procédure événementielle en choisissant dans les listes déroulantes en haut du module de code : oEventsTextChanged et SLEvent :

 
Sélectionnez

Private Sub oEventsTextChanged_SLEvent(sender As Variant, args As Variant)
Stop
End Sub


C'est cette procédure qui sera exécutée sur changement de texte dans un des contrôles.
On utilise le même objet pour les événements des deux contrôles, il faudra retrouver le contrôle initiateur de l'événement.

Comme il y a un point d'arrêt dans la procédure, si on modifie un texte l'exécution s'arrête.
On va en profiter pour étudier les paramètres sender et args.
sender est l'élément initiateur de l'événement.
sender.getvalue("name") nous permet de retrouver son nom.

Si on survole args on voit :
- TextChangedEventArgs pour l'utilisateur ;
- RoutedEventArgs pour le mot de passe.

Le type d'argument est donc fonction de l'événement.
Pour l'événement TextChanged du Login.
TextChangedEventArgs est défini ici : Membres TextChangedEventArgs.

Pour l'événement PasswordChange du Password :
RoutedEventArgs est défini ici : Membres RoutedEventArgs.

Je n'ai malheureusement pas réussi à extraire d'informations intéressantes de cet argument.
J'aurais aimé retrouver le nom de l'événement déclencheur (TextChanged ou PasswordChange).
Il faudra alors utiliser plusieurs objets de type clEventsSL pour gérer différents types d'événements.

Pour notre cas on va laisser tout dans la même procédure et vérifier le nom de l'objet sender.
Le texte est également lisible par VBA, en utilisant GetValue sur le sender pour lire ses propriétés.

 
Sélectionnez

Private Sub oEventsTextChanged_SLEvent(sender As Variant, args As Variant)
Select Case sender.getvalue("name")
   Case "Login"
       Debug.Print "Modification de Login :" & sender.getvalue("text")
   Case "Password"
       Debug.Print "Modification de Password :" & sender.getvalue("password")
End Select
End Sub

VII-H-2. Gestion de la souris


Comme pour les événements de texte auparavant, il faut d'abord déclarer un objet en en-tête de module avec WithEvents :

 
Sélectionnez

Private WithEvents oEventsMouseDown As clEventsSL


Puis instancier cet objet à l'ouverture du formulaire par exemple :

 
Sélectionnez

Set oEventsMouseDown = New clEventsSL


Créez enfin la procédure événementielle en choisissant dans les listes déroulantes en haut du module de code : oEventsMouseDown et SLEvent :

 
Sélectionnez

Private Sub oEventsMouseDown_SLEvent(sender As Variant, args As Variant)
stop
End Sub


Pour déclencher l'événement il faut affecter l'objet à l'événement de l'élément voulu.
On va capturer les événements de click avec le bouton gauche de la souris sur le canevas racine.

 
Sélectionnez

oSL.content.findname("rootcanvas").addeventlistener "MouseLeftButtonDown", oEventsMouseDown


Ce code est à placer après la boucle d'attente de chargement du plugin.

Si on clique sur la page (sauf si on clique sur une zone de saisie), l'événement est déclenché.
Le code s'arrête sur l'instruction Stop, le temps de faire quelques investigations.

Survolez sender => il s'affiche son type : Canvas.
Pour voir son nom :

 
Sélectionnez

MsgBox sender.getvalue("name")


Quel que soit l'élément sur lequel vous cliquez, on affiche "rootcanvas" qui est le nom de l'élément auquel on a affecté le gestionnaire d'événement.
L'événement est donc transmis de l'élément sur lequel on clique à l'élément qui le contient.

Si vous survolez args (ou que vous affichez la valeur de args.toString), vous voyez : MouseButtonEventArgs.

Cet argument contient des informations intéressantes et exploitables :
- Source est l'élément déclencheur de l'événement (potentiellement différent de sender).
- GetPosition nous permet de trouver la position du clic (absolue ou relative).

 
Sélectionnez

MsgBox "Gérer par " & sender.tostring & " : " & sender.getvalue("name") & vbCrLf & _
      "Envoyé par " & args.getvalue("Source").tostring & " : " & args.getvalue("Source").getvalue("name") & vbCrLf & _
      "Position absolue " & args.GetPosition(Null).getvalue("x") & ":" & args.GetPosition(Null).getvalue("y") & vbCrLf & _
      "Position relative " & args.GetPosition(args.getvalue("Source")).getvalue("x") & ":" & _
                                   args.GetPosition(args.getvalue("Source")).getvalue("y")


Ce code nous affiche par exemple :

Gérer par Canvas : rootcanvas
Envoyé par Canvas : secondcanvas
Position absolue 380:229
Position relative 378:182


En remarque bien que sender est toujours le canevas racine, et que la valeur de "Source" est l'élément sur lequel on a cliqué.
Pour trouver la position, il faut préciser Null pour avoir la position absolue (c'est-à-dire l'origine en haut à gauche de la page).
Pour avoir la position à l'intérieur d'un élément, il faut préciser cet élément dans l'appel à GetPosition.
GetPosition renvoie une structure de type Point qui possède des propriétés X et Y.

Lien MSDN pour la gestion de la souris : Silverlight Mouse Support

Les fichiers xaml, HTML et un fichier Excel de test de ce chapitre sont disponibles sur ce lien.

VII-I. Dessiner avec la souris


Pour dessiner des traits, on peut utiliser l'objet InkPresenter.

Un trait est ajouté à la collection Strokes et possède des attributs de taille et couleur.

Voici un exemple à télécharger pour Excel : Tutoriel souris(miroir HTTP)

Lien MSDN pour l'objet InkPresenter : InkPresenter

Les fichiers xaml, HTML et un fichier Excel de test de ce chapitre sont disponibles sur ce lien.

Si vous n'avez pas Excel, voici l'extrait des codes :

fichier silvermouse.html
Sélectionnez

<HTML>
<script type="text/javascript"> 
            
function OnErrorEventHandler(sender, errorArgs)
{
   // Create the error message to display.
   var errorMsg = "Silverlight Error: \n\n";
            
   // Specify error information common to all errors.
   errorMsg += "Error Type:    " + errorArgs.errorType + "\n";
   errorMsg += "Error Message: " + errorArgs.errorMessage + "\n";
   errorMsg += "Error Code:    " + errorArgs.errorCode + "\n";
            
   // Determine the type of error and add specific error information.
   switch(errorArgs.errorType)
   {
       case "RuntimeError":
           // Display properties specific to RuntimeErrorEventArgs.
           if (errorArgs.lineNumber != 0)
           {
               errorMsg += "Line: " + errorArgs.lineNumber + "\n";
               errorMsg += "Position: " +  errorArgs.charPosition + "\n";
           }
           errorMsg += "MethodName: " + errorArgs.methodName + "\n";
           break;
       case "ParserError":
           // Display properties specific to ParserErrorEventArgs.
           errorMsg += "Xaml File:      " + errorArgs.xamlFile      + "\n";
           errorMsg += "Xml Element:    " + errorArgs.xmlElement    + "\n";
           errorMsg += "Xml Attribute:  " + errorArgs.xmlAttribute  + "\n";
           errorMsg += "Line:           " + errorArgs.lineNumber    + "\n";
           errorMsg += "Position:       " + errorArgs.charPosition  + "\n";
           break;
       default:
           break;
   }
   // Display the error message.
   alert(errorMsg);
}
            
function OnResizeEventHandler(sender, args)
{
    sender.width = sender.gethost().content.actualwidth;
    sender.height = sender.gethost().content.actualheight;
    sender.findname("rootgrid").width = sender.gethost().content.actualwidth;
    sender.findname("rootgrid").height = sender.gethost().content.actualheight;
}
            
</script>
<body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">
   <object id="SilverLight1" data="data:application/x-silverlight," type="application/x-silverlight-2" 
    width="100%" height="100%">
     <param name="source" value="silvermouse.xaml"/>
    <param name="onerror" value="OnErrorEventHandler" />
    <param name="onresize" value="OnResizeEventHandler" />
      <!-- Display installation image. -->
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50303.0" 
                  style="text-decoration: none;">
         <img src="http://go.microsoft.com/fwlink/?LinkId=161376" 
               alt="Get Microsoft Silverlight" 
               style="border-style: none"/>
       </a>
   </object>
</body>
</HTML>
fichier silvermouse.xaml
Sélectionnez

<Canvas Name="rootcanvas" Background="#50FFFF00" xmlns="http://schemas.microsoft.com/client/2007"> 
<!-- La Grille -->
<Grid Name="rootgrid" ShowGridLines="False">
    <!-- Définition des colonnes -->
    <Grid.ColumnDefinitions>
           <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <!-- Définition des lignes -->
    <Grid.RowDefinitions>
           <RowDefinition Height="Auto" />
           <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <!-- Texte d'en-tête dans la première ligne -->
    <TextBlock Name="titre" Grid.Row="0" Grid.Column="0" TextAlignment="Center">
           Dessinez en cliquant sur le bouton gauche de la souris.
       </TextBlock>
    <!-- Canevas dans la deuxième ligne -->
    <!-- <Border BorderThickness="2" BorderBrush="Blue" Grid.Row="1" Grid.Column="0">-->
        <InkPresenter Grid.Row="1" Grid.Column="0" Background="#500000FF" Name="inkPresenterElement"/>
    <!--</Border>-->
</Grid>
</Canvas>
code VBA du formulaire
Sélectionnez

Option Explicit
            
Private oSL As Object
Private WithEvents oInkPresenterMouseDown As clEventsSL
Private WithEvents oInkPresenterMouseMove As clEventsSL
Private WithEvents oInkPresenterMouseUp As clEventsSL
Private newStroke As Integer ' indice du trait en cours de dessin (doit être un entier Integer)
Private Const daWidth As Integer = 2
Private Const daHeight As Integer = 2
Private Const daColor As String = "Blue"
Private Const daOutlineColor As String = "Black"
            
Private Sub oInkPresenterMouseDown_SLEvent(sender As Variant, args As Variant)
   sender.CaptureMouse
   ' Ajout du trait
   SLAddStroke "<Stroke><Stroke.DrawingAttributes/></Stroke>", Me.ctlNav.Document, _
                   "SilverLight1", "inkPresenterElement"
   ' Indice = nombre de traits - 1
   newStroke = sender.getvalue("strokes").getvalue("Count") - 1
   ' attributs
   With sender.getvalue("strokes").getitem(CInt(newStroke)).getvalue("DrawingAttributes")
       .Width = daWidth
       .Height = daHeight
       .Color = daColor
       .OutlineColor = daOutlineColor
   End With
   ' ajoute les points
   sender.getvalue("strokes").getitem(CInt(newStroke)).getvalue("StylusPoints").AddStylusPoints _
                           args.GetStylusPoints(args.getvalue("Source"))
End Sub
            
Private Sub oInkPresenterMouseMove_SLEvent(sender As Variant, args As Variant)
On Error GoTo gestion_erreurs
If newStroke <> -1 Then
   sender.getvalue("strokes").getitem(CInt(newStroke)).getvalue("StylusPoints").AddStylusPoints _
                           args.GetStylusPoints(args.getvalue("Source"))
End If
Exit Sub
gestion_erreurs:
' Erreur si dépasse le inkpresenter
End Sub
            
Private Sub oInkPresenterMouseUp_SLEvent(sender As Variant, args As Variant)
newStroke = -1
sender.ReleaseMouseCapture
End Sub
            
Private Sub UserForm_Initialize()
newStroke = -1
Set oInkPresenterMouseDown = New clEventsSL
Set oInkPresenterMouseMove = New clEventsSL
Set oInkPresenterMouseUp = New clEventsSL
Me.ctlNav.Navigate ThisWorkbook.Path & "/silvermouse.html"
End Sub
            
Private Sub ctlNav_DocumentComplete(ByVal pDisp As Object, URL As Variant)
Set oSL = pDisp.Document.getElementById("silverlight1").Object
While Not oSL.IsLoaded
   DoEvents ' indispensable pour ne pas tout bloquer
Wend
oSL.content.findname("inkPresenterElement").addeventlistener "MouseLeftButtonDown", oInkPresenterMouseDown
oSL.content.findname("inkPresenterElement").addeventlistener "MouseMove", oInkPresenterMouseMove
oSL.content.findname("inkPresenterElement").addeventlistener "MouseLeftButtonUp", oInkPresenterMouseUp
End Sub
            
'------------------------------------------------------------------------------
' Insère un trait dans un InkPresenter dans silverlight
'------------------------------------------------------------------------------
' pxaml : code XAML
' pDocument&#160;: un document HTML
' pObjet&#160;: l'Id de l'objet Silverlight dans le document HTML
' pElement&#160;: le nom de l'élément parent
' pPosition&#160;: position optionnelle de l'élément
'------------------------------------------------------------------------------
Public Function SLAddStroke(ByVal pxaml As String, pDocument As Object, pObject As String, pElement As String)
Dim sScript As String
sScript = "var plugin = document.getElementById('" & pObject & "');" & vbCrLf & _
         "var element = plugin.content.CreateFromXaml('" & pxaml & "');" & vbCrLf
sScript = sScript & "plugin.content.FindName('" & pElement & "').strokes.add (element);"
pDocument.parentWindow.execscript sScript
End Function

L'exemple ci-dessus utilise le module de classe clEventsSL vu précédemment.

Voici une image obtenue avec cet exemple :

Image non disponible

VII-J. Capture d'écran

Il n'existe pas de méthode standard (sauf dans le code XAML managé compilé).

On peut juste envisager une capture d'écran via l'API Windows.

Je n'ai pas à ce jour de code à vous proposer...

VII-K. Images et Vidéos

Le plugin Silverlight accepte un nombre limité de formats de vidéos et d'images.

VII-K-1. Images

Silverlight ne connaît que les formats d'image PNG et JPG.

Exemple d'intégration d'une image :

 
Sélectionnez

<Image Name="MyImage" Source="logoofficeweb.jpg" Width="150"/>


Les images peuvent aussi être utilisées pour remplir une forme :

 
Sélectionnez

 <Ellipse Width="200" Height="100" Stroke="Black" StrokeThickness="1">
   <Ellipse.Fill>
   <ImageBrush ImageSource="logoofficeweb.jpg"/>
   </Ellipse.Fill>
 </Ellipse>

VII-K-2. Vidéos

Vous trouverez sur MSDN la liste des formats de vidéo supportés : Supported Media Formats, Protocols, and Log Fields.

Pour insérer une vidéo, utilisez l'élément MediaElement :

 
Sélectionnez

<MediaElement Name="MyVideo" Source="myvideo.wmv" Width="150" Height="150"/>


Les vidéos peuvent aussi être utilisées pour remplir une forme :

 
Sélectionnez

 <MediaElement Name="MyVideo" Source="myvideo.wmv" Opacity="0.0" IsMuted="True"/>
 <Ellipse Width="150" Height="150">
   <Ellipse.Fill>
   <VideoBrush SourceName="MyVideo"/>
   </Ellipse.Fill>
 </Ellipse>


Il faut d'abord créer un MediaElement nommé et le rendre invisible (Opacity) et en sourdine (IsMuted).
Réutilisez ensuite le nom de cet élément dans l'élément VideoBrush.

Pour plus d'information sur l'élément VideoBrush :VideoBrush Overview.

VII-L. Transformations

Utilisez l'élément RenderTransform pour appliquer des transformations à un élément :

Exemple d'une image dont les transformations sont centrées sur l'origine (avec RenderTransformOrigin).
L'image est tournée de 30 ° et réduite en taille de moitié.

 
Sélectionnez

<Canvas xmlns="http://schemas.microsoft.com/client/2007">
<Image Name="MyImage" Source="logoofficeweb.jpg" Width="350" RenderTransformOrigin="0.5,0.5">
    <Image.RenderTransform>
        <TransformGroup>
          <RotateTransform Name="MyRotate" Angle="30" />
        <ScaleTransform Name="MyScale" ScaleX="0.5" ScaleY="0.5" />
        </TransformGroup>
    </Image.RenderTransform>
</Image>
</Canvas>

VII-M. Animations

Des animations peuvent être obtenues avec un élément Storyboard.

Sur le lien ci-dessus, vous avez un exemple d'animation d'opacité.

Voici le code XAML pour animer le même rectangle de gauche à droite :

 
Sélectionnez

<Canvas xmlns="http://schemas.microsoft.com/client/2007">
<Rectangle
   Name="MyAnimatedRectangle"
   Width="100"
   Height="100"
   Fill="Blue">
   <Rectangle.Triggers>
     <EventTrigger RoutedEvent="Rectangle.Loaded">
       <BeginStoryboard>
         <Storyboard>
           <DoubleAnimation
             Storyboard.TargetName="MyAnimatedRectangle"
             Storyboard.TargetProperty="(Canvas.Left)"
             From="0" To="400" Duration="0:0:2" AutoReverse="True" RepeatBehavior="Forever" />
         </Storyboard>
       </BeginStoryboard>
     </EventTrigger>
   </Rectangle.Triggers>
 </Rectangle>
</Canvas>

Le tutoriel suivant, bien qu'écrit pour C#, contient des informations intéressantes pour les animations en XAML : Les animations avec Silverlight.

VII-N. Intégrer le code XAML dans la page HTML : Online XAML

Au lieu d'utiliser un fichier externe, il est possible d'intégrer le code XAML à la page HTML.

Voici un article de MSDN qui explique cette possibilité : Utilisation du XAML inline.

VII-O. Peut-on utiliser des barres de défilement ?

Non, l'objet ScrollView n'est disponible que pour une application compilée (API managée).
On peut agrandir le plugin (par exemple une taille à 200 %) et avoir alors des barres de défilement HTML sur tout le plugin, mais pas sur un élément particulier.

VII-P. Conclusion Silverlight

Si le code XAML non compilé est très restreint par rapport à ce que Silverlight peut offrir, on arrive tout de même à faire de beaux écrans.
L'intérêt de Silverlight dans Office reste à démontrer ; un écran d'accueil (SplashScreen) pourrait être du plus bel effet ;o).


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2011 Thierry GASPERMENT. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.