Le premier site francophone dédié au développement Pocket PC

Développer des contrôles mobiles pour Visual Studio .NET 2003 et CF
Auteur
Laurent Docquir
Date 13 mai 2003
 

 

Introduction

Cet article s'adresse aux développeurs désirant utiliser le .NET Compact Framework (.NET CF) pour développer des applications mobiles sur des appareils Windows CE.

La philosophie .NET en général apporte un grand nombre d'avantages aux développeurs d'applications. L'un de ces avantages est de pouvoir développer de nouvelles classes qui s'appuient sur des classes existantes. Je veux bien évidemment parler de l'héritage.

Il y a grosso-modo deux types de classes. Celles qui possèdent une interface graphique et celles qui n'en possèdent pas. Dans le premier cas, il s'agit d'un contrôle ou Windows Control. Dans le second cas, il s'agit tout simplement une classe.

Lors de la conception d'une application, les contrôles sont placés sur des formulaires par le développeur. Par contre, les classes sont instanciées dynamiquement par le code.

Si vous faites du développement .NET sur PC, vous pouvez développer des classes et des contrôles en utilisant respectivement les projets Class Library et Windows Control Library.

Par contre si vous faites du développement .NET pour Windows CE. Vous devez utiliser un projet Smart Device Application. Lors de la création d'un tel projet, un assistant vous permet de spécifier le type de plate-forme que vous visez ainsi que le type de projet que vous désirez réaliser.



Comme vous pouvez le constater, en regardant la capture d'écran ci-dessus, il n'existe pas de type de projet Windows Control Library pour les smart devices ! Pour développer des classes réutilisables, seul le projet Class Library est disponible.

Nous voici donc arrivé au point de départ de mon propos. Je vais vous montrer comment développer un contrôle mobile en partant d'un projet de classe.

Implémentation du contrôle mobile PictureButton

Comme d'habitude, afin d'illustrer mon article, il me faut un exemple à la fois simple et efficace. J'ai choisi de vous montrer comment implémenter un bouton pouvant être muni d'une icône. Ce contrôle, que nous appellerons dorénavant PictureButton, n'est pas fourni en standard dans la boîte à outils de Visual Studio .NET.

Création du projet

Commençons par créer un projet Smart Device Application en C#. Choisissez un répertoire et nommez votre projet PictureButton. Ceci vous permettra d'avoir un assembly PictureButton.dll. Optez ensuite pour un projet Class Library lorsque l'assistant vous le demandera.

PS : rien ne vous empêche de transposer le code de cet article en VB .NET si le coeur vous en dit.

Mise en place de la classe PictureButton

Vous devriez maintenant avoir un fichier class1.cs qui contient une implémentation rudimentaire d'une classe .NET. Nous allons donc opérer plusieurs modifications sur cette classe. Voici ce que je vous propose :

  1. Renommez le fichier class1.cs en quelque chose de plus adéquat : picturebutton.cs par exemple.
  2. Changez le namespace de la classe. Par défaut le namespace devrait correspondre au nom de votre projet. Remplacez le par quelque chose qui a plus de sens. Pour ma part j'ai choisi de le nommer EZOS.Mobile. Ceci me permettra de placer tous mes contrôles dans le même namespace.
  3. Changez le nom de la classe class1 en PictureButton
  4. Faites hériter votre classe PictureButton de la classe System.Windows.Forms.Control. N'oubliez pas de déclarer le namespace System.Windows.Forms au moyen du mot clé using

Si vous avez bien suivi mes indications, vous devriez obtenir un code similaire à ceci :

Ajout des propriétés du contrôle

Notre contrôle PictureButton doit avoir deux propriétés essentielles : l'icône à afficher et le texte. Pour faire simple, j'ai choisi d'implémenter ces deux propriétés comme suit :

  • Une propriété Icon de type System.Drawing.Icon qui contiendra directement les données de l'icône.
  • Une propriété Text de type string dont la valeur correspondera au texte à afficher à côté de l'icône.

De ces deux propriétés, seule Icon va devoir être implémentée. En effet, la propriété Text est une propriété commune des contrôles .NET. De ce fait elle est prise en charge par la classe Windows.Forms.Control. Comme notre PictureButton dérive justement de cette classe, nous héritons aussi de la propriété Text.

Afin d'ajouter la propriété Icon, faites un click droit sur votre classe PictureButton dans la fenêtre Class View. Ensuite dans le menu contextuel, choisissez Add -> Add Property...

Remplissez de manière adéquate le formulaire suivant :

Un appui sur le bouton 'Finish' va générer les méthodes d'accès set et get à la propriété.

Vous pouvez remarquer sur la capture d'écran qu'il n'est pas possible de spécifier directement System.Drawing.Icon comme type de propriété. Une fois le code généré, il va falloir changer le type string en type System.Drawing.Icon.

De plus déclarez une variable membre privée m_icoBtn de type System.Drawin.Icon. Cette dernière servira à stocker la valeur de la propriété Icon.

Voici donc le code de la propriété Icon :

Notez l'instruction this.Invalidate() dans la méthode set. Elle sert à forcer un réaffichage du contrôle lorsque la valeur de la propriété Icon change.

En ce qui concerne la propriété Text, il y a quand même un petit quelque chose à coder dans notre classe. Il faut s'assurer que le contrôle sera rafraîchi lorsque le texte change. Ce comportement n'est pas implémenté par défaut. Je vous propose donc de réagir à l'évènement TextChanged de la classe de base Control.

Pour gérer cet évènement, ajouter cette ligne code dans le constructeur de votre PictureButton :

this.TextChanged +=new EventHandler(PictureButton_TextChanged);

Normalement, vous ne devrez pas taper le code à droite du signe '=' ! Dès que vous aurez tapé le caractère '=', l'éditeur de Visual Studio .NET va vous proposer une déclaration par défaut pour la fonction de gestion de l'évènement. Appuyez deux fois sur la touche Tab pour accepter les propositions.

Ajoutez ensuite la ligne this.Invalidate() à l'intérieur de l'event handler comme suit :

Affichage du picture button à l'exécution

Le rendu graphique d'un contrôle est toujours effectué dans l'évènement Paint. Cet évènement est déclenché par le framework chaque fois qu'il est nécessaire de mettre à jour l'affichage du contrôle. Vous allez donc déclarer une méthode qui va être associée à l'évènement Paint. Dans le constructeur de votre classe PictureButton, ajoutez la déclaration suivante :

this.Paint +=new PaintEventHandler(PictureButton_Paint);

Dans la function PictureButton_Paint ajoutez le code qui affiche l'icône et le texte. Dans le code ci-dessous, l'icône et le texte sont centrés verticalement par rapport à la hauteur du contrôle. De plus je réalise les opérations non pas directement sur la fenêtre mais sur une bitmap en mémoire. Lorsque le bouton est dessiné, je transfère le contenu de la bitmap dans la zone client du contrôle. Ceci permet d'éviter des effets de clignotement du bouton lors de l'affichage.

Voici le code de l'évènement Paint :


Voici la première étape du travail réalisée : vous avez maintenant une classe PictureButton développée avec le framework compact.

La deuxième étape du développement consiste à fournir au développeur le moyen de placer votre contrôle PictureButton sur une fenêtre directement à partir de l'environnement de développement Visual Studio .NET.

Prise en compte du mode 'design time'

Pour ajouter votre contrôle dans la boîte à outils de Visual Studio .NET, vous allez devoir fournir une seconde classe PictureButton mais qui cette fois utilisera le Framework .NET complet. Cette nouvelle classe devra avoir les mêmes propriétés, méthodes et évènements. Par contre il n'est pas obligatoire que le code à l'intérieur de ces propriétés et méthodes soit identique à la version .NET CF. Avant de plonger dans le code, je me permets de faire un petit rappel des choses afin de vous expliquer le pourquoi.

En fait, un contrôle graphique possède deux modes de fonctionnement appelés mode design-time et mode run-time. Dans le mode design-time, un contrôle est instancié par Visual Studio .NET pour permettre au développeur de visualiser le contrôle et d'interagir avec lui. Ce mode est appelé design-time tout simplement parce que le développeur est en train de concevoir son application. Quand un contrôle s'exécute en design-time, généralement il n'offre pas 100% de ses fonctionnalités : il se limite bien souvent à produire un rendu graphique à l'intérieur de la fenêtre hôte.

Par contre, quand l'application est réellement exécutée, le contrôle est alors instancié en mode run-time. Dans ce mode, le contrôle offre toutes ses fonctionnalités.

La question qui vous vient probablement à l'esprit maintenant est : " Mais comme puis-je savoir si mon contrôle est exécuté en mode design-time ou run-time ? ". Dans le cas d'un contrôle mobile la réponse est subtile. La particularité d'un contrôle mobile est que en mode design-time, il s'exécute sur votre PC et qu'il utilise le Framework .NET complet. Par contre, en mode run-time, il s'exécute sur votre appareil mobile et utilise le Framework .NET compact.

Ceci nous amène tout droit à la réponse: il va falloir développer deux exemplaires de la classe, une pour chaque mode.

Dans la première partie de l'article, nous avons développé la classe utilisant le Framework compact et destinée à tourner en mode run-time. Il nous reste donc à développer la classe pour le design-time qui cette fois-ci devra utiliser le Framework complet.

Vous pourriez créer un nouveau projet et redévelopper votre contrôle pour le Framework .NET complet. Nous allons cependant procéder d'une autre manière.

Je vous propose de repartir du même code source et d'y faire quelques aménagements pour le mode design-time. Ces aménagements seront sous l'influence de directives de compilation conditionnelles. De cette manière, nous serons en mesure d'assembler le code pour le framework complet et le framework compact à partir du même source.

Pratiquement, à chaque fois que nous placerons du code spécifique au mode design-time, nous le mettrons à l'intérieur d'un bloc #if #endif comme suit :

#if NETCFDESIGNTIME
Code spécifique
#endif

RuntimeAssemblyAttribute

Une des premières choses à faire pour intégrer votre contrôle dans l'éditeur Visual Studio .NET est de lui ajouter certains attributs. Pour rappel, un attribut est une information qui n'est pas du code mais qui est utilisé soit par le compilateur soit par le framework lui-même pour activer certains mécanismes. Un attribut est ajouté entre crochets devant la classe, méthode ou propriété qu'il qualifie.

Le premier attribut à ajouter est l'attribut RuntimeAssemblyAttribute. Il permet de spécifier à Visual Studio .NET quelques informations liées à la version runtime de l'assembly qui sera téléchargé sur l'appareil mobile.

#if NETCFDESIGNTIME
[assembly: System.CF.Design.RuntimeAssemblyAttribute("PictureButton, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")]
#endif

RuntimeAssemblyAttribute spécifie le numéro de version, la langue et une clé publique si vous désirez développer une classe globale. Notez que le numéro de version est censé coincider avec la version de l'assembly .NET CF.

NOTE : Par défaut la valeur du numéro de version dans le fichier AssemblyInfo.cs est 1.0.*, ce qui signifie que les deux derniers chiffres sont générés automatiquement par Visual Studio à chaque nouveau build de l'assembly. Dès lors, il devient fastidieux de modifier le RuntimeAssemblyAttribute en conséquence après chaque build.

Je vous conseille donc de spécifier un numéro de version complet dans le fichier AssemblyInfo.cs de votre projet comme suit :

[assembly: AssemblyVersion("1.0.0.0")]

Attributs de la propriété Icon

Les attributs liés à une propriété de contrôle imposent un comportement particulier à Visual Studio .NET. Placez le code suivant devant la déclaration de la propriété Icon

#if NETCFDESIGNTIME
 [System.ComponentModel.Category("Custom")]
 [System.ComponentModel.DefaultValueAttribute("")]
 [System.ComponentModel.Description("L'icone du bouton")]
#endif
public string Icon
 {
  get
  . . .
 }

l'attribut Category vous permet de spécifier l'emplacement de la propriété Icon dans la fenêtre des propriétés. J'ai choisi 'Custom' dans cet exemple et voici ce que cela donne dans l'éditeur :

L'attribut DefaultValueAttribute vous permet de donner une valeur par défaut à la propriété lorsque le développeur dépose votre contrôle sur un formulaire.

Enfin l'attribut Description vous permet de donner une brève description de la propriété.

Affichage en mode design-time

La méthode PictureButton_Paint sera appelée pour effectuer le rendu du contrôle tant dans l'éditeur Visual Studio .NET que dans l'application mobile elle-même. Ce qui signifie que le code de l'évènement Paint fourni plus haut fonctionne aussi pour le mode design time.

Génération des assemblies

Pour générer l'assembly destiné à l'appareil mobile, vous allez tout simplement construire votre projet à partir du menu de Visual Studio .NET 2003. Puisque vous avez opté pour un projet Smart Device, l'assembly visera le framework .NET compact.

Par contre pour générer l'assembly destiné à l'environnement de développement, nous allons invoquer le compilateur C# directement sur la ligne de commande.

Voici la ligne de commande à utiliser :

csc /noconfig /define:NETCFDESIGNTIME /target:library
/out:design.PictureButton.dll PictureButton.cs AssemblyInfo.cs
/res:EZOS.Mobile.PictureButton.bmp /r:"C:\Program Files\Microsoft
Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows
CE\Designer\System.CF.Design.dll" /r:"C:\Program Files\Microsoft
Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows
CE\Designer\System.CF.Windows.Forms.dll" /r:"C:\Program
Files\Microsoft Visual Studio .NET
2003\CompactFrameworkSDK\v1.0.5000\Windows
CE\Designer\System.CF.Drawing.dll" /r:System.Windows.Forms.dll
/r:System.Drawing.dll /r:System.dll /r:System.XML.dll
/r:System.Data.dll /nowarn:1595

Je vous conseille de placer cette ligne de commande dans un fichier .bat, de manière à ne pas devoir la retaper sans cesse

Quelques détails concernant la commande :

  • /define :NETCFDESIGNTIME permet de définir la constante NETCFDESIGNTIME. Ceci vous permet de compiler les lignes de codes à l'intérieur des #if NETCFDESIGNTIME ... #endif
  • /out :design.PictureButton.dll permet de spécifier le nom de l'assembly
  • Le fichier EZOS.Mobile.PictureButton.bmp contient l'icône qui sera ajouté dans la boîte à outil de Visual Studio .NET. Remarquez que cette image porte exactement (à la casse près) le même nom que la classe PictureButton. Ceci est primordial si vous voulez que Visual Studio affiche votre image.
  • le reste des commandes (/r) servent à référencer les assemblies que vous utilisez dans votre code.

Attention :

  • Il se peut que vous deviez adapter les chemins utilisés dans cette ligne de commande en fonction du chemin d'installation de Visual Studio .NET 2003 sur votre station de travail.
  • Cette ligne de commande ne peut être exécutée dans une boîte DOS classique. Vous devez démarrez une boîte DOS spécifique à Visual Studio .NET 2003. Cette dernière se trouve dans le menu démarrer, quelque part à l'intérieur du dossier Visual Studio .NET 2003.
  • Veuillez aussi noter que cette ligne de commande génère un assembly nommé design.PictureButton.dll. Ceci vous évite de générer deux fichiers identiques pour le mode design-time et run-time.

Installation du contrôle dans votre environnement de développement

Vous devriez maintenant être en possession de deux assemblies :

  • PictureButton.dll destiné à l'appareil mobile
  • Design.PictureButton.dll destiné à Visual Studio .NET

Copiez ces deux fichiers respectivement dans les répertoires:

  • C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE
  • C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Designer

Démarrez Visual Studio .NET, executez un click droit sur la fenêtre boîte à outils et sélectionnez l'entrée de menu Add/Remove Items ...

Sur l'écran suivant, cliquez sur le bouton Browse et sélectionnez l'assembly design.PictureButton.dll que vous venez juste de copier. Vous pourrez ensuite voir votre contrôle apparaitre dans la liste des composants .NET disponibles.

Utilisation du PictureButton

Votre contrôle PictureButton se trouve maintenant dans la boîte à outil de Visual Studio .NET et peut donc être utilisé au même titre que n'importe quel autre contrôle. Créez un nouveau projet Windows Forms pour Smart Device et collez un contrôle PictureButton sur le formulaire principal. La capture d'écran ci-dessous vous montre le formulaire, la fenêtre des propriétés et la fenêtre des outils :

 

Voici maintenant l'application en cours d'exécution sur l'appareil mobile.

Conclusion

Bien qu'il n'y ait pas de projet spécifique pour contrôles mobiles, il est tout à fait possible d'en développer en utilisant la procédure décrite dans cet article. Cette procédure est quelque peu contraignante mais offre de belles perspectives pour créer des éléments graphiques ré-utilisables à souhait. D'ailleurs si vous cherchez de tels éléments sur Internet, vous en trouverez aussi sous forme de classes simples. Dans ce cas, ils ne seront pas intégrés à Visual Studio .NET mais plus gênant encore : vous devrez générer le code de création et d'initialisation de ces éléments graphiques par vous-même.

Sources de cet article


Laurent Docquir

 

Copyright 2001-2004 - Tous droits réservés
Toutes les autres marques et produits présents dans ces pages sont la propriété exclusive de leurs sociétés respectives.