Une remarque pertinente ?
Une critique impertinente ?
Un lynchage en règle ?
Une invitation sous les tropiques ?

Ecrivez-moi !
Conçu et enseigné tel qu'en lui même, avec pertes, fracas et humour de qualité supérieure            
 par Christophe Darmangeat dans le M2 PISE du Master MECI (Université Paris 7)            

 
 
 
  
 
 
 
Partie 11
Les graphismes
 
Des graphismes avec VB.NET, il y aurait évidemment beaucoup à dire, et cela dépasserait largement le cadre de ce cours. Mais il y a tout de même quelques éléments de base pas si évidents, auxquels je voudrais consacrer ce chapitre... haut en couleurs, comme il se doit.
1. Couleurs et Propriétés
Même si jusqu'ici nous ne nous sommes pas particulièrement arrêtés sur cette question, votre proverbial sens de l'observation vous aura sans doute indiqué que la quasi-totalité des contrôles possèdent des propriétés désignant leur(s) couleur(s). Ainsi, Backcolor et ForeColor permettent de modifier respectivement la couleur d'arrière-plan et la couleur d'avant-plan (celle du texte) des contrôles.
Certes. Mais comment spécifie-t-on une couleur ? Il existe pour cela deux grands moyens. Lorsque nous réglons une des propriétés de couleurs à la main, dans la fenêtre design, nous voyons que s'offrent deux possibilités : soit le choix d'une couleur prédéfinie (via les onglets web et system), ou la composition d'une couleur entièrement paramétrable (via l'onglet Personnaliser, suivi d'un clic droit). Eh bien, le code nous propose globalement la même alternative.

1.1 La structure System.Drawing.Color
Elle correspond au choix d'une couleur au sein d'une palette prédéfinie (web ou system). Ces couleurs sont au nombre de 174, ce qui donne déjà un assez large choix. Les couleurs dites web porteront ainsi de jolis noms fleuris, tels LightCoral, Orchid ou SeaShell. Ces couleurs s'afficheront donc de la même manière sur toutes les machines où sera installée l'application. Les couleurs système, elles, porteront des noms rappelant leur utilisation dans Windows, comme InactiveBorder, ScrollBar ou Menu. Choisir une couleur system signifie que cette couleur variera d'une machine à l'autre, selon la manière dont l'utilisateur aura choisi de personnaliser Windows. Bon, jusque là, pas de problème.
En ce qui concerne le code, on retombe sur une technique déjà abordée. Soit on se tape l'intégrale, c'est-à-dire que pour mettre le fond de Button1 en jaune, on devra écrire quelque chose du genre :
Button1.BackColor = System.Drawing.Color.LemonChiffon
Soit on opte pour la version abrégée, ce qui supposera d'avoir préalablement "importé" l'espace de noms par :
Imports System.Drawing
Ce qui permettra ensuite de se contenter d'un :
Button1.BackColor = Color.LemonChiffon

1.2 Définir une couleur personnalisée
Tout comme on peut le faire à la main, on peut dans le code définir sa propre couleur. Celle-ci doit respecter la structure des couleurs prédéfinies, à savoir être composée de quatre octets. La couleur peut donc être spécifiée par la méthode FromArgb, qui requiert en argument un ensemble de quatre nombres de 0 à 255 séparés par des points-virgules.
Le premier de ces arguments représente le degré d'opacité de la couleur (de 0 pour transparent, à 255 pour une couleur pleine). Les trois nombres suivants représentent dans l'ordre la quantité de rouge, de vert et de bleu. Ainsi, pour colorer un bouton en bleu, écrira-t-on :
Button1.BackColor = Color.FromArgb(255, 0, 0, 255)
Il est toutefois possible de passer la méthode FromArgb uniquement avec trois paramètres. Dans ce cas, ceux-ci désignent les couleurs, et par défaut, l'opacité est considérée comme maximale.
Et voilà de quoi s'amuser, bien qu'on soit censé avoir passé l'âge des coloriages.
Voilà un exercice où le traitement des couleurs sera l'occasion d'une bonne révision sur les collections et les événements. Gymnastique mentale garantie...
Exercice
Exécutable
Sources
Home cinema

2. Images et Contrôles
Là encore, il n'aura pas échappé à vos yeux de lynx qu'en mode design, un certain nombre de contrôles acceptent volontiers que leur fond soit constitué d'une image. C'est notamment le cas pour les Form et les Buttons, avec la propriété BackgroundImage.
Nous parlerons plus loin de la manière dont on peut affecter cette propriété par du code. En attendant, il faut dire quelques mots des contrôles dont le rôle spécifique est de contenir des images.

2.1 La classe ImageList (rappel)
Il y a tout d'abord l'ImageList, dont nous avons déjà fait la connaissance. Je rappelle que ce contrôle :
  • est un véritable tableau d'images, qui peut donc en contenir autant qu'on le souhaite.
  • reste invisible lors de l'exécution, ainsi que toutes les images qu'il contient.
Il ne peut donc servir que de "réservoir à images" pour les autres contrôles, qui iront y puiser les images nécessaires au fur et à mesure de leurs besoins, durant l'exécution de l'application.

2.2 La classe PictureBox
Si l'on veut qu'à un endroit de la Form, se trouve telle ou telle image, alors il faut utiliser le contrôle adéquat, à savoir PictureBox. Celui-ci possède une propriété Image, qui indiquera son contenu. Le contrôle PictureBox prend en charge les principaux formats d'image : JPEG, GIF, Bitmap, métafichiers (WMF), icônes... Il ne gère pas, en revanche, les vidéos.
Une propriété notable des PictureBox est SizeMode. Celle-ci peut prendre quatre valeurs, qui modifieront les propriétés du contrôle et/ou de l'image dans le cas où ceux-ci ne possèdent pas les mêmes dimensions  :
  • aucun : ni le contrôle ni l'image ne changent de taille. Cela peut signifier que l'image sera rognée, et/ou que le contrôle débordera de l'image. L'image est alignée en haut à gauche du contrôle.
  • stretch : l'image est automatiquement étirée afin que sa taille s'adapte à celle du contrôle qui la contient.
  • autosize : la taille du contrôle est automatiquement adaptée à celle de l'image qu'il contient.
  • centerimage : les tailles de l'image et du contrôle ne sont pas modifiées, mais l'image est centrée par rapport au contrôle.
Remarque limpide :
Le contrôle PictureBox est incapable de gérer les images transparentes, quelle que soit la manière dont on s'y prend, et même si l'image qu'il contient est elle-même transparente.
Moralité, si l'on veut pouvoir gérer des images transparentes (et cela peut arriver plus souvent qu'on ne le croit), on sera obligé de faire appel à un autre contrôle que PictureBox.
Rendez-vous dans ce chapitre pour en savoir plus.
3. Gérer intelligemment les images
On en vient à présent à la manière de gérer les images dans une application. Il y a deux stratégies, possédant chacune leurs avantages et leurs inconvénients, qu'il vaut mieux connaître avant de faire des choix discutables et pénalisants.
Le premier mouvement, lorsqu'on veut utiliser des images, c'est évidemment de les intégrer aux contrôles (PictureBox, ImageList, Form, etc. en mode design, donc en tant que propriétés par défaut de ces contrôles. C'est la manière la plus simple de procéder, qui va avoir deux conséquences :
  • les fichiers images vont être considérés par vb comme une partie intégrante de la Form. A l'enregistrement de celle-ci, les informations qu'ils contiennent seront donc recopiées dans un fichier annexe du fichier *.vb, portant le même nom et l'extension *.resx
  • les fichiers image vont être directement incorporés à l'exécutable. L'avantage, c'est que celui-ci n'aura jamais de problème pour les trouver. Mais l'inconvénient, c'est que cette méthode peut alourdir considérablement l'exécutable en termes d'octets occupés, et peut finir par créer un monstre incapable de tourner sur certaines machines à la puissance limitée.
Voilà pourquoi cette technique, si elle a l'avantage de la facilité, est à réserver aux petites images, et qu'elle doit être proscrite dès qu'on a affaire à des images volumineuses et/ou trop nombreuses.
Pour celles-ci, comment faire ? Pour s'y retrouver, il va falloir en quelque sorte raisonner à rebrousse-poil, en partant du but à atteindre pour remonter vers les moyens à mettre en oeuvre. C'est parti :
Au final, que voulons-nous ? Que le(s) fichier(s) image(s) dont l'exécutable va avoir besoin soient stockés indépendamment de cet exécutable, afin de conserver à celui-ci la sveltesse qui fait toute son élégance.
Pour cela, il faut que l'exécutable contienne une ou plusieurs instructions donnant l'ordre de charger tel ou tel fichier image dans tel ou tel contrôle. Cette instruction est la méthode FromFile, qui appartient à la classe Image. On écrira ainsi :
PictureBox1.Image = Image.FromFile (nom du fichier)
C'est là qu'arrive un petit souci. Le nom du fichier, cela sous-entend de devoir préciser le répertoire dans lequel il se trouve. Dans le cas contraire, cette instruction serait incapable de fonctionner et provoquerait une erreur. Il faut donc absolument :
  • spécifier correctement, lors de l'emploi de la méthode FromFile, le chemin relatif où va se trouver le fichier image par rapport à l'exécutable qu'est notre application.
  • faire en sorte que lors de l'installation de cette application sur différentes machines, et ce, quel que soit le répertoire où s'effectuera l'installation, le fichier image se trouvera bel et bien dans le chemin relatif voulu.
Pour le moment, nous ne traiterons que du premier point. Le second, ce sera pour un peu plus tard, dans le chapitre 13 de ce cours.
Prenons un exemple. Admettons que nous choisissions de regrouper toutes les images dont notre application aura besoin au cours de son exécution, dans un sous-répertoire de l'exécutable, appelé "Pic".
Le chargement du fichier "Charlot.jpg" dans le contrôle Portrait devra donc dire ; "va chercher le fichier Charlot.jpg qui se trouve dans le répertoire Pic, celui-ci étant un sous-répertoire de l'endroit où tu es en train de t'exécuter." Ceci peut s'effectuer de la manière suivante (j'ai découpé le code en plusieurs instructions plus plus de lisibilité, mais on pourrait bien sûr aller plus vite :
Actuel = Directory.GetCurentDirectory
Fic = Actuel & "\Pic\Charlot.jpg"
Portrait.Image = Image.FromFile (Fic)
Et voilà. Je rappelle que cette méthode suppose de paramétrer l'installation pour que le sous-répertoire Pic soit automatiquement créé et que le fichier Charlot.jpg y soit déposé. Mais le gros avantage, c'est que l'exécutable reste d'une taille raisonnable.
Remarque généraliste :
Cette technique doit être mise en oeuvre, avec quelques aménagements, pour tous les fichiers annexes dont une application peut avoir besoin : fichiers de données, vidéos, sons, etc.
4. Deux mots sur les méthodes graphiques
Je ne m'étendrai pas sur cet aspect, qui ne peut intéresser que des programmeurs se lançant des un type d'applications un peu spécialisé. Mais autant savoir que VB.Net donne facilement accès aux classes et aux méthodes de Windows qui permettent de tracer directement des points et des formes à l'écran.
Le premier point à savoir est que l'on peut, par du code, tracer aussi bien des graphismes en mode Bitmap (c'est à dire en faisant du point par point) qu'en mode vectoriel (en raisonnant sur des formes).
Le second point est qu'on peut dessiner à l'écran (sur un contrôle), à l'imprimante (sur un objet PrintDocument) ou en mémoire (le résultat restant ensuite disponible pour n'importe quel usage, y compris être enregistré dans un fichier).
En mode Bitmap, on peut ainsi positionner des points, des rectangles, des ellipses, tracer des traits paramétrables avec un crayon ou un pinceau virtuel, faire des dégradés.
En mode vectoriel, il sera possible de tracer des lignes, des polygones, des cercles, des ellipses, des courbes de Bézier...
Bon, bref, j'avais dit que je ne serais pas long sur le sujet, eh bien je vais tenir parole.