Jusqu'à présent, lorsque nous voulions utiliser des contrôles dans une application, nous avons toujours procédé de la même manière : au départ, on crée tous les contrôles nécessaires à un moment ou à un autre dans l'application, quitte à en cacher provisoirement quelques uns hors de la vue de l'utilisateur. Et ensuite, on permet à l'utilisateur d'effectuer certaines actions sur ces contrôles.
Cette stratégie, dans 99 % des cas, donne des résultats tout à fait convenables. Mais pour le 1% restant, il est bon de connaître une autre manière de s'y prendre : celle qui va nous permettre de créer et de faire disparaître les contrôles au cours de l'exécution de l'application.
Un exemple de ce 1%, nous est donné par un jeu comme le démineur, que tout le monde connaît pour l'avoir pratiqué de longues heures durant, à l'insu de son chef de bureau. Au démineur, les règles du jeu sont invariables. Mais en revanche, l'utilisateur a le droit de choisir entre plusieurs tailles de damier. Pire, il peut même choisir librement le nombre de cases en ligne et colonne.
Une manière barbare de programmer cela, serait de créer au départ le plus grand damier autorisé pour le jeu ; puis ensuite, à la lumière du choix effectué par le joueur, de masquer les cases qui n'ont pas lieu d'être. Mais c'est une solution d'une part bien peu élégante (et, question philosophique, l'élégance n'est-elle pas la marque de tout bon programmeur ?), d'autre part très lourde en termes de ressources mémoire, puisqu'on va mobiliser de la place pour gérer des dizaines de contrôles qui s'avèreront le plus souvent aussi superflus que le peigne de Fabien Barthez.
Il convient donc de posséder la technique permettant de créer, de manipuler et de détruire des contrôles par des instructions figurant dans l'application elle-même. Ce n'est pas vraiment difficile, et en plus, c'est une excellente manière de se préparer à la programmation objet proprement dite.
Alors, comment procéder ? Réfléchissons un peu, ça ne pourra pas nous faire de mal.
Si nous créons un contrôle de toutes pièces au cours de l'exécution, et si l'on veut que ce contrôle puisse servir à quelque chose, il va bien falloir qu'existent les procédures d'événements qui lui sont liées. Or, on n'a aucun moyen de créer en cours de route lesdites procédures (un programme ne peut pas écrire des lignes de programme). Ainsi, si l'on veut que notre contrôle soit autre chose qu'un simple élément décoratif, il faut que les procédures événementielles qui s'y rapportent aient été crées à l'avance. Comment est-ce possible ? Tout simplement en ne créant dynamiquement que des éléments de groupes, dont on aura préalablement défini le premier élément et les procédures associées.
Quatre-vingt-dix-neuf fois sur cent, il faut donc appliquer la stratégie suivante :
On crée à la main l'élément numéro zéro d'un groupe de contrôles (quitte à le masquer provisoirement), et on définit ses propriétés.
On écrit les procédures événementielles liées à ce groupe
On engendre de manière dynamique les autres éléments du groupe, dans la quantité souhaitée.
Pour créer un élément supplémentaire d'un groupe de contrôles, on emploiera le code suivant :
Load NomduGroupe(i)
où "NomduContrôle" est évidemment le nom du groupe, et "i" l'index de l'élément qui sera créé.
Remarque importante : tout nouvel élément, créé par Load, d'un groupe, est situé par défaut à l'emplacement exact de l'original, et invisible. Il faudra donc le plus souvent modifier ses propriétés Top et Left, ainsi que sa propriété Visible.
Pour supprimer un élément d'un groupe de contrôles, on écrira :
Unload NomduGroupe(i)
C'est aussi simple que cela ! Pour peu qu'on ne fasse pas n'importe quoi, la création et la destruction dynamiques de contrôles ne posent donc pas la moindre difficulté. En fin de compte, pour conclure sur ce point : même si le cheminement diffère un peu, les instructions Load et Unload nous permettent de parvenir au même résultat avec les groupes de contrôles que l'instruction Redim avec les tableaux de variables.