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 3
Premiers contrôles
Nous en savons à présent suffisamment pour commencer
à mettre pour de bon les mains dans le cambouis. Ouvrons donc la boîte
à outils, et regardons ça de près. Que trouvons-nous ?
1. La classe Form
La classe Form (qu'on appelle également
le formulaire), issue de la classe Windows.Form,
est l'élément de base, obligé et fondamental,
de toute application
VB
pour Windows.
C'est sur une Form, et uniquement sur une Form, que nous pourrons
éventuellement poser d'autres contrôles. Et même
si on peut à la
rigueur la rendre invisible (mais il faut être un peu tordu),
de toutes façons, elle est quand même là. Corollaire
de cette proposition, c'est également dans le code correspondant à la Form que seront
rassemblées toutes les procédures
événementielles liées aux contrôles que
nous aurons créés sur cette
Form.
Nous pouvons d'entrée noter plusieurs propriétés de la classe
Windows.Form
(donc de tous les objets Form créés à partir de cette classe), propriétés
que nous retrouverons dans la plupart, sinon dans la totalités des
autres contrôles proposés par VB :
Une
erreur (grossière) à ne
pas faire :
Il ne faut évidemment pas confondre les propriétés Name et Text, dont le rôle n'a vraiment rien à voir. Me.Size = New Size(500, 300)
Heureusement, il y a un moyen de
contourner l'obstacle et de se simplifier considérablment l'existence. Plutôt que nous embêter avec ce type
Size structuré, nous pouvons, en fouinant un peu - découvrir que nous
avons directement accès à deux autres propriétés, Height et Width,
beaucoup plus maniables car de type Integer. Ainsi, la ligne ci-dessus
pourra avantageusement être remplacée par :
Me.Width = 500
Me.Height = 300 ...ce qui n'est tout de même pas plus tordu, loin s'en faut.
Remarque pinailleuse :
La propriété Size désigne les dimensions extérieures d'un contrôle. Si l'on désire connaître, ou définir, ses dimensions intérieures (la zone « cliente » du contrôle), on dispose de la propriété Clientsize, qui possède la même structure. La différence entre Size et Clientsize est particulièrement sensible avec les Form, en raison de l'existence de la barre de titre. Me.Location = New Location(0, 0)
...et le plus facile :
Me.Top = 0
Me.Left = 0
Remarque millimétrée :
Avec Top, Left, Width et Height, on dispose d'un moyen très simple de dimensionner et positionner n'importe quel contrôle en cours d'exécution. Pour une fois qu'on a une arme simple et efficace, on aurait bien tort de l'oublier ! D'autres propriétés de la classe Form sont propres à cette
classe, et ne se retrouvent pas - ou rarement - dans d'autres classes.
Il s'agit par exemple de :
Côté événements, les Form sont capables d'en recevoir - autrement
dit, d'en gérer - un certain nombre. Parmi ceux-ci, les plus
importants, pour commencer, sont sans doute Load et Activate. Je m'y
arrête d'autant plus volontiers qu'on a souvent une fâcheuse tendance
à les confondre, alors qu'ils sont loin d'être identiques.
Définitions
:
L'événement Load correspond au chargement de la fenêtre en mémoire vive. L'événement Activate correspond au fait que la Form spécifiée devient la fenêtre active. Dans le cas d'une application qui ne compte qu'une
seule Form, les deux événements se confondent. En effet, l'unique Form se charge au lancement de
l'application, devenant par la même occasion la Form active, et le restant
sans discontinuer jusqu'à la fin de cette application.
Mais dès qu'une application compte plusieurs Form, les choses se passent
tout autrement. Toutes les Form vont en effet être chargées au lancement de
l'application (déclenchant ainsi les événements Load une fois pour toutes). Mais une seule sera
active. Par la suite, à chaque fois que l'utilisateur passera d'une Form à
l'autre, il redéclenchera l'événement Activate pour la Form sur laquelle
il vient d'atterrir.
Les événements Activate et Load se prêtent particulièrement bien à des
instructions d'initialisation : c'est là, avant que l'utilisateur ait eu le
temps de faire quoi que ce soit, qu'on remet les compteurs à zéro, qu'on
remet les cases et les zones de saisie à blanc (ou qu'on y réécrit les
valeurs par défaut), etc.
2. La classe Button
Les spécialistes de la langue de Chexpire auront bien
sûr reconnu derrière ce nom sibyllin la classe servant à créer les... boutons.
On retrouve pour les contrôles créés à partir de la
classe Button les propriétés générales déjà évoquées
ci-dessus pour les Form : Name, bien sûr, mais aussi Text,
Size, Location,
Visible et bien d'autres.
Si la classe Button nous intéresse, ce n'est pas tant pour ses
propriétés (ce n'est pas lui faire injure que de remarquer qu'elles
restent somme toute limitées) que pour sa capacité à gérer un certain
nombre d'événements, à commencer par le plus fréquent d'entre eux :
Click. Nous allons donc pouvoir gérer des
procédures déclenchées automatiquement par le clic sur un bouton, en
suivant simplement les règles de syntaxe exposées précédemment
ici-même.
Avec tout ce que vous avez lu jusque là, vous avez largement de
quoi commencer à vous dérouiller les pattes (et les neurones).
Pour réussir ces exercices, vous disposez de presque toutes les connaissances nécessaires.
La seule exceptions concerne les deux versions du Cache-cache, qui correspondent au même résultat obtenu par deux stratégies différentes (soit on a deux boutons et on les masque alternativement, soit on a un seul bouton qu'on déplace). Dans les deux cas, vous allez tout de même avoir besoin de savoir comment on écrit les tests, sujet sur lequel ce passage du prochain chapitre éclairera votre lanterne. 3. Une parenthèse nécessaire : le paramètre Sender
Nous interrompons à présent le cours normal de nos émissions pour un flash d'information.
Il est en effet grand temps de dire quelques mots d'un des deux paramètres en entrée qui ponctuent toutes les procédures
événementielles que nous avons créées : je veux parler de Sender (en anglais : « l'envoyeur »).
En fait, si les procédures événementielles ne pouvaient gérer qu'un seul événement à la fois, ce paramètre ne
servirait strictement à rien. Mais le truc, c'est que les procédures peuvent, si on le souhaite, gérer plusieurs évenements à la fois.
On peut imaginer, par exemple, une procédure appelée Truc, qui serait déclenchée aussi bien par un clic sur Bouton1 que sur Bouton2,
et dont la ligne de titre aurait alors la physionomie suivante :
Private Sub Truc(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Bouton1.Click, Bouton2.Click
En pareil cas, on pourrait avoir besoin, au sein de cette procédure, de savoir lors d'une exécution donnée
quel est l'objet qui est à l'origine de cette exécution, autrement dit lequel, de Bouton1 ou de Bouton2, a été cliqué.
Eh bien, c'est à cela que sert Sender.
On remarque que ce paramètre est défini par un drôle se type :
System.Object. Autrement dit, Sender est une variable objet,
c'est-à-dire une une variable qui pointe sur un objet. Et en l'occurrence, pas n'importe lequel : celui qui a déclenché
l'exécution de la procédure. On peut donc dire que selon les cas, Sender vaudra
Bouton1 ou Bouton2. Et on va pouvoir utiliser cette variable à l'intérieur de la procédure,
soit en lecture (pour récupérer une information concernant l'objet, par exemple son Name) soit même en écriture
(pour modifier une ou plusieurs propriétés de l'objet pointé).
Sender pointant sur un contrôle, cette variable possède en effet la caractéristique
remarquable de posséder toutes les propriétés et les méthodes de l'objet qu'elle désigne. On pourra donc, par exemple, parler de
Sender.text
ou de
Sender.visible
etc.
Remarque sioux :
J'entends déjà une objection qui se veut définitive : « comment pourrait-on utiliser une propriété de Sender en écriture, puisque ce paamètre est passé à la procédure ByVal, donc en lecture seule ? ». Cela paraît imparable, mais en réalité, il y a un détail qui change tout : c'est que Sender n'est pas le contrôle lui-même, mas seulement un pointeur qui le désigne. Ainsi, le fait qu'il soit passé par valeur interdit qu'on change l'objet désigné par la variable Sender. Mais il n'interdit pas qu'on puisse, en quelque sorte par ricochet, modifier des propriétés de cet contrôle. Vous pouvez à présent reprendre Indiana Jones en faisant en sorte de simplifier le code.
4. La classe Label
On peut maintenant reprendre le cours de notre propos, et commençant par évacuer deux considérations essentielles.
Ces points étant désormais réglés, nous pouvons passer
aux choses sérieuses et parler brièvement de
ce contrôle, qui correspond donc à une simple étiquette posée sur une Form (généralement, pour éclairer l'utilisateur sur tel ou tel point,
commenter une image ou une zone, etc.)
L'élément sans doute le plus important à retenir pour les Label est
qu'il ne s'agit pas de zones de saisie pour l'utilisateur. Ce qui
n'empêche pas le contenu d'un Label de pouvoir être modifié par le
code en cours d'exécution, ni le Label de pouvoir recevoir un certain
nombre d'événements, dont le Click.
Signalons toutefois trois propriétés que possède la classe Label :
Et voilà tout ce qu'il y a d'important à dire sur la classe Label pour le moment.
5. La classe LinkLabel
Il s'agit d'une sous-classe de la classe Label.
En termes de programmation objet, on dira que la classe
LinkLabel hérite de la
classe Label. L'héritage est un concept très important quand on
commence à faire sérieusement de la programmation objet. Et on a beau
être contre l'héritage dans la vie en général, il faut reconnaître qu'en
programmation, c'est une invention très utile.
On reviendra plus loin et (un peu) plus en détail sur ce qu'est
l'héritage,
mais on peut profiter de l'occasion que nous donne le LinkLabel pour donner
une première définition : une classe qui hérite d'une autre (on parle
alors d'une classe fille qui hérite d'une classe parente)
possède
toutes les propriétés et méthodes
de cette classe parente, plus d'autres. En l'occurrence, un contrôle
LinkLabel possède toutes les propriétés et méthodes d'un contrôle
Label, avec quelques facultés supplémentaires.
Cette aptitude supplémentaire des LinkLabel, c'est de
gérer un lien
hypertexte, qui va permettre d'ouvrir un navigateur et d'aller à
l'adresse web indiquée. Par défaut, c'est l'ensemble du texte du
LinkLabel qui sert de lien hypertexte, mais on peut très bien
paramétrer l'affaire pour que seule une portion du texte joue ce rôle.
Et si cette portion est réduite à rien, alors le lien est tout
simplement désactivé.
Voici donc les principales propriétés propres à la classe LinkLabel :
Il y a une série d'autres propriétés, liées notamment aux différentes
couleurs que doit prendre le lien selon les situations (actif, visité, etc.), mais elles ne devraient vous poser aucun problème.
En revanche, il faut maintenant ajouter ce qui concerne le
lancement du navigateur avec l'url correcte. Car en réalité, à
proprement parler, la classe LinkLabel en est incapable : tout ce
qu'elle sait faire, c'est générer un événement LinkClicked, qui ne se
produit que lorsque le lien est actif et que l'utilisateur a cliqué
dessus.
Il nous faudra donc gérer la procédure correspondant à cet
événement, en y introduisant l'instruction permettant d'ouvrir le
navigateur avec l'url correcte, c'est-à-dire en y entrant le code
suivant :
System.Diagnostics.Process.Start("url souhaitée")
Bon, ben... c'est reparti pour un tour !
L'exercice qui suit ne présente aucune difficulté particulière. Il n'implique ni astuce, ni
connaissance qui ne figurerait pas dans les lignes précédentes.
En revanche, c'est une excellente occasion de vérifier que vous avez les idées bien en place en ce qui concerne les propriétés, les procédures, les événements, les instructions, toussa, quoi, et que du coup, vous pouvez vous en servir autrement qu'en jetant le tout pêle-mêle au hasard et en caressant l'écran avec un trèfle à quatre feuilles en espérant que ça marche. |