| 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. |