Rappel : Ce cours est enseigné dans la
spécialité PISE du Master MECI (Université Paris 7)
par Christophe Darmangeat

Partie 4
contrôles et groupes
1. Les Cases
Il existe sous Windows deux sortes de cases :
  • les cases dites "cases à cocher" (Checkbox): Elles sont carrées, et indépendantes les unes des autres, même si elles sont regroupées dans un cadre pour faire plus joli.
  • les cases dites "cases d’option", voire "boutons radio" (OptionButton). Elles sont rondes et font toujours partie d’un ensemble (dessiné par l’objet Frame). Au sein d’un ensemble de cases d’option, jamais plus d’une seule case ne peut être cochée à la fois.
Illustrations :


 

Moralité, avant de mettre des cases et d’écrire le code qui s’y rapporte, il faut bien se demander de quel type de cases on a besoin.
Une fois ce préambule posé, il n’y a pas de problèmes particuliers, hormis que pour des cases d'option, il faut toujours créer le Frame avant de poser des cases à l’intérieur de ce Frame. Dans le cas contraire, le langage ne reconnaîtra pas les cases comme faisant partie du même ensemble, et elles auront un comportement erratique.
Sinon, la propriété la plus intéressante d’une case est de loin celle qui nous permet de savoir si elle est cochée ou non. Cette propriété s’appelle Value.
  • Value prend la valeur True ou False lorsqu’elle concerne les cases d’option.
  • Value prend la valeur 1 ou 0 lorsqu’elle s’applique aux cases à cocher. Cette différence de traitement peut paraître aberrante, mais il faut se rappeler que les cases à cocher peuvent aussi posséder un état intermédiaire grisé. Auquel cas leur propriété Value prend la valeur 2.
  • Comme toute propriété, Value peut être utilisée en écriture (pour initialiser telle ou telle case au moment où elle arrive à l’écran) ou en lecture (pour tester quelle case a coché l’utilisateur, et accomplir du coup un traitement ou un autre).
    Dans les corrigés de ces exercices, on vous assène que le code est lourd et maladroit. Pourtant, c'est le seul que vous êtes pour le moment en état de produire ! Mais c'est pour vous mettre l'eau à la bouche : attendez un peu la suite, et vous allez voir ce que vous allez voir...
    Nom de l'exercice
    Exécutable
    Sources
    Rater le Coche
    Options Onéreuses



    2. Les groupes de contrôles
    Avec les deux exercices qui précèdent, on constate un alourdissement considérable du code, qui devient redondant pour un certain nombre d'objets.
    Cela tient au fait que jusqu'à présent, nous avons toujours considéré que chaque contrôle était un objet complètement indépendant de ses congénères. Cela se manifestait de deux manières :
    • lors de leur création, nous allions toujours chercher l’objet dans la boîte à outils, en nous abstenant soigneusement de procéder à des copier coller.
    • par conséquent, chaque objet possédait une propriété Name bien à lui, qui nous permettait de le désigner sans ambiguïté en écrivant le code. Et du coup, chaque objet possédait ses propres procédures événementielles, distinctes de celles liées aux autres objets.
    Mais cette stratégie induit lors de certains programmes une lourdeur qui ne vous aura pas échappé. Lorsque plusieurs objets de même type remplissent des tâches voisines, voire semblables (cf. les deux exercices précédents), on se retrouve avec une flopée de procédures événementielles (une par objet, parfois davantage) qui se ressemblent beaucoup, voire qui sont carrément semblables.
    La création d’un groupe de contrôles a pour but d’alléger tout ceci. Comment ça marche, me direz-vous ? Eh bien voici.
    Lors de la création des contrôles (mettons, une série de quatre cases à cocher), on procède dorénavant par copier-coller, en prenant soin, s'il s'agit de cases d'options, que le collage s’effectue bien au sein du Frame (sinon, elles ne marcheront pas correctement ensemble). A la question "souhaitez-vous créer un groupe de contrôles?", on répond sans réserves par l’affirmative.
    Dès lors, les quatre objets ainsi créés seront en fait des membres d’un même groupe. En Français, cela signifie que ces quatre objets porteront le même nom (Name) mais affublé d’un Index qui servira à les identifier individuellement. Tout cela rappelle furieusement les tableaux, hein ? C'est bien normal, puisque c'en est.
    Si j’osais une métaphore ailée (mais non filée), je dirais que le groupe est au contrôle ce que le tableau est à la variable simple. Limpide, non ? J'ajoute pour conclure que Index est une propriété – c'est logique – de tout élément d'un groupe de contrôles, définissant son indice (propriété à ne surtout pas confondre avec TabIndex, qui définit son ordre dans la tabulation, ce qui n'a rien à voir avec la choucroute).
    Donc, résumons nous.
    Si on a créé un groupe de 4 contrôles de classe Checkbox le nom par défaut de ce groupe sera Check1. Rebaptisons-le CaseCarrée pour plus de clarté. On aura alors CaseCarrée(0), car l'Index commence à zéro comme pour tout tableau qui se respecte, CaseCarrée(1), CaseCarrée(2) et CaseCarrée(3).
    Si on a un traitement à effectuer sur les quatre cases, on pourra dorénavant écrire une boucle, par exemple pour décocher tout ça :
    For i = 0 to 3
    CaseCarrée(i).Value = 0
    Next i
    Déjà, on se marre bien. Mais c’est encore plus rigolo quand on crée la procédure associée à ce groupe. Cela produit un intitulé du genre :
    Private Sub CaseCarrée_Click (Index as Integer)

    End Sub
    Eh oui, vous avez bien vu. Cela signifie que dorénavant, pour un événement donné, il n’y a plus qu’une seule procédure pour l’ensemble des contrôles du groupe !
    Quant à la variable Index, dont vous voyez que Visual Basic la crée automatiquement en tant que paramètre en entrée de cette procédure, elle contient à chaque exécution de la procédure, l'indice de l'élément du groupe qui vient de déclencher l'événement.
    Ainsi par exemple, si au sein de cette procédure, on a besoin de savoir quelle case a été cliquée, il suffit de tester la variable Index, qui, en l'occurrence, vous l’aurez deviné, peut valoir de zéro à trois.
    A noter qu'Index est ici une simple variable, à ne pas confondre avec la propriété Index des éléments des groupes de contrôles. Donc, si ce nom de variable vous semble trop lourdingue, rien ne vous interdit de le modifier.
    Formulons tout cela d'une traite : Index est le nom par défaut du paramètre en entrée pour la procédure événementielle, paramètre qui prend à chaque exécution la valeur de la propriété Index du membre du groupe qui a déclenché cette exécution.
    Avec tout cela, certains programmes vont pouvoir s'alléger considérablement. Moralité, en VB, c’est comme pour tout le reste, pour pouvoir être fainéants, devenons compétents.
    Les exercices liés aux groupes reprennent ceux que l'on vient d'effectuer à propos des cases. Mais à présent, ils doivent bien sûr être programmés très différemment... Les sources présentées ici donnent la solution employant la technique des groupes.
    Pour les Options Onéreuses, il y a au moins deux moyens d'éviter une fastidieuse série de tests.
    A Table et Cinq à la suite sont deux autres exemples simples du gain de temps que peuvent permettre les groupes.
    A signaler que pour le Cavalier Déchaîné (déjà nettement plus difficile), il existe plusieurs astuces (plus ou moins méchantes) pour s'épargner de longs fragments de code répétitifs.
    Que voulez-vous, quand on aime les vicieusetés algorithmiques, on ne se refait pas.
    Nom de l'exercice
    Exécutable
    Sources
    Rater le Coche
    Options Onéreuses
    A Table !
    Cinq à la suite
    Le Cavalier Déchaîné



    3. Les Listes
    3.1 deux contrôles de listes
    Les listes classiques dans Windows peuvent posséder ou non deux caractéristiques.
    • Elles peuvent être modifiables : c’est-à-dire que l’utilisateur a la possibilité d’entrer un élément qui ne figure pas au départ dans la liste. Cette caractéristique concerne donc les données de la liste proprement dites.
    • Elles peuvent être déroulantes : c’est-à-dire qu’on ne voit qu’un seul élément de la liste à la fois, et qu’il faut cliquer sur la flèche du côté pour "déplier" la liste. Cette caractéristique joue donc uniquement sur l’aspect de la liste, et aucunement sur la manière dont les données sont gérées.
    Une liste peut donc prendre quatre têtes, selon qu’elle est modifiable ou non, déroulante ou non ("chez les papous, y a les papous à poux et les papous pas à poux, etc.")
    VB fournit deux contrôles de liste :
    • une liste dite simple : contrôle ListBox
    • une liste dite modifiable : contrôle ComboBox
    Le gag (ce Bill Gates, quand même, quel rigolo), c’est qu’en réalité, la liste dite modifiable est aussi une liste déroulante… Alors, pour résumer la situation, voici un petit récapitulatif de ce qu’il faut utiliser :
     
    LISTE
    Non déroulante
    Déroulante
    Non modifiable
    ListBox
    ComboBox
    Style = 2
    Modifiable
    ComboBox
    Style = 1
    ComboBox
    Style = 0 (défaut)

    Propriétés indispensables :
    • ListIndex : renvoie ou définit l’indice de l’élément actuellement sélectionné. En fait, en interne, VB gère les listes un peu à la manière des tableaux. Il attribue donc à chaque élément d’une liste un indice, cet indice commençant toujours à zéro. A noter que si aucun élément n'est sélectionné dans la liste, la propriété Listindex vaut -1.
    • List : Savoir quel est l’indice de l’élément sélectionné dans une liste, c’est bien. Mais savoir à quel texte correspond cet indice, c’est mieux ! Cette propriété renvoie en clair (sous forme de texte) un élément d’une liste en fonction de son indice. Il s’agit donc, chose assez rare, d’une propriété qui nécessite un argument (le numéro d’indice).
    Pour récupérer sous forme de texte l’élément actuellement sélectionné dans la liste appelée Produits, on écrira donc le code suivant :
    NuméroProduit = Produits.ListIndex
    NomProduit = Produits.List(NuméroProduit)
    MsgBox "Vous avez choisi le produit : " & NomProduit
    Ou plus directement :
    NomProduit = Produits.List(Produits.ListIndex)
    MsgBox "Vous avez choisi le produit : " & NomProduit
    Toutefois, il faut noter que les contrôles ComboBox nous simplifient grandement la vie, puisqu'à la différence des ListBox, ils nous proposent directement une propriété Text. Ainsi, si Produits est un contrôle ComboBox, et uniquement dans ce cas, on pourra écrire :
    NomProduit = Produits.Text
    MsgBox "Vous avez choisi le produit : " & NomProduit

    Autres propriétés intéressantes :
    • ListCount, qui renvoie le nombre d’éléments d’une liste (propriété numérique)
    • Multiselect, qui permet la sélection multiple (propriété booléenne)
    • Sorted, qui trie automatiquement les éléments d’une liste (propriété booléenne)

    Méthodes à connaître
    Nous découvrons avec les contrôles ListBox et ComboBox des méthodes qu'il est indispensable de connaître afin de gérer des objets de type liste :
    • AddItem Chaîne : ajoute l'élément Chaîne à une liste (un argument supplémentaire, facultatif, permet éventuellement de spécifier à quel indice l'élément doit être inséré).
    • RemoveItem (indice) : supprime de la liste l'élément possédant l'indice spécifié.
    • Clear : efface tous les éléments d’une liste
    Comme à l'accoutumée, voilà deux petits exercices pour se mettre tout cela en tête.
     
    Nom de l'exercice
    Exécutable
    Sources
    Primeurs
    Listes Baladeuses
    3.2 Trois autres contrôles pour des usages spéciaux
    Il n'est pas rare que dans une application, on doive permettre à l'utilisateur de naviguer dans le disque dur, les répertoires, les fichiers, etc. (comme dans la commande Fichier – Ouvrir de tout logiciel).
    Pour réaliser cela, on va avoir recours à trois contrôles supplémentaires, spécialisés, dont le rôle est de reproduire des outils familiers sous Windows :
    • DriveListBox : qui fournit automatiquement la liste des lecteurs logiques disponibles sur la machine où tourne l'application.
    • DirListBox qui fournit automatiquement la liste des répertoires contenus dans une unité donnée
    • FileListBox qui fournit automatiquement la liste des fichiers contenus dans un répertoire donné.
    Illustration :

    La présence de ces contrôles soulage votre tâche, mais ne vous épargne toutefois pas totalement d’écrire un chouïa de code, afin de les faire fonctionner ensemble. Ces trois objets étant des cas particuliers de contrôle liste, s’y appliquent éventuellement List, Listcount et Listindex.
    Mais pour gérer la mise à jour de ces contrôles les uns en fonction des autres, les propriétés suivantes sont indispensables (et suffisantes) :
    • Drive : qui renvoie ou définit l'unité logique actuellement en vigueur dans un contrôle DriveListBox
    • Path : qui renvoie ou définit le chemin actuellement en vigueur dans un contrôle DirListBox ou dans un contrôle FileListBox
    • Filename : qui renvoie ou définit le fichier actuellement sélectionné dans un contrôle FileListBox.
    Allez, un peu de pratique n'a jamais fait de mal à personne :
     
    Nom de l'exercice
    Exécutable
    Sources
    Promenade