TD : Mise en oeuvre des formulaires et contrôles
(2)
Avant de continuer, si vous ne l'avez pas encore fait, lisez
la
page traitant des messages à l'utilisateur. Nous allons nous en servir pour
détecter quel événement a lieu à quel moment.
Les formulaires (suite)
Dans cette deuxième partie nous allons voir, de façon
pratique, comment appeler un formulaire et "espionner" les événements
qui en découlent afin de mieux maîtriser les différents aspects de
l'interface utilisateur (ou IHM : Interface Homme Machine).
Nous allons rajouter, sur notre formulaire de menu (frmMenu), un
bouton nous permettant d'appeler le deuxième formulaire qui, à terme,
sera une calculatrice très simplifiée mais qui nous permettra l'étude des
propriétés, méthodes et événements des contrôles de type "TextBox"
qui sont les contrôles les plus utilisés dans les IHM.
Avant tout, il serait intéressant d'enregistrer un formulaire
comme le "frmMenu" sous forme de modèle afin de ne pas avoir
à reprendre, à chaque nouvelle feuille, les propriétés vu au début de ce TD.
C'est une bonne façon d'être sûr de ne rien oublier ! Toutefois, le nom
"frmMenu" n'est pas un bon choix pour un modèle. Nous allons donc
créer un nouveau formulaire dans le but de créer ce modèle puis, nous
l'utiliserons pour créer notre deuxième formulaire pour l'application
PForms.vbp.
Pour créer un nouveau formulaire, utilisez le menu "Projet
/ Ajouter une feuille" et sélectionnez le modèle "de
base" qui s'appelle "form" dans la liste de modèles qui
vous est proposée. Vous voici avec une nouvelle feuille pour laquelle vous
allez saisir les valeurs de propriétés suivantes :
| Propriété |
Valeur |
| Name |
frmModlDlg |
| Caption |
Modèle "Boite de dialogue" |
| BorderStyle |
Fixed dialog |
| ControlBox |
False |
Vous allez ensuite, utiliser le menu "Fichier / Enregistrer
frmModlDlg" pour stocker le fichier frm dans le répertoire des modèles
(C:\Program Files\Microsoft Visual Studio/VB98/Template/Forms si vous avez
conservé le répertoire par défaut à l'installation de VB6). Le simple fait
d'enregistrer un formulaire dans ce répertoire en fait un modèle disponible et
utilisable à chaque commande "Projet / Ajouter une feuille". Nous
allons en faire la preuve tout de suite !
Commencez par supprimer ce formulaire modèle du Projet. Pour
cela, dans la liste des formulaires du projet (fenêtre de l'explorateur de
projet Ctrl-R), cliquez sur le nom du formulaire avec le bouton droit de la
souris et choisissez la commande "Supprimer" dans le menu contextuel.
Nous éviterons, ainsi, d'écraser, par inadvertance, le modèle que nous venons
de créer.
Formulaire
appelé :
Utilisons, maintenant, ce nouveau modèle pour faire notre
future calculatrice .... Utilisez le menu "Projet / Ajouter une
feuille" et, dans la liste des modèles qui vous est proposée, vous allez
trouver, en fin de liste, votre nouveau modèle "frmModlDlg".
Sélectionnez le puis cliquez sur "Ouvrir" pour obtenir un formulaire
basé sur le modèle.
La première chose à faire est de donner un nom et un titre à
ce nouvel objet et à l'enregistrer dans le répertoire du projet. Utilisez les valeurs
de propriétés suivantes :
| Propriété |
Valeur |
| Name |
frmCalc |
| Caption |
Calculatrice VB6 |
Enregistrez ensuite (en cliquant sur la disquette de la
barre d'outils) ce nouveau fichier en acceptant le nom par défaut qui vous est
proposé (frmCalc.frm) mais en faisant bien attention de le sauver dans le répertoire
du projet et non dans le répertoire des modèles cette fois !
Nous allons ajouter un bouton "Fermer" (cmdClose)
comme nous l'avons fait pour notre menu principal. Ajoutez un bouton de commande
au formulaire frmCalc et utilisez les valeurs de propriétés suivantes :
| Propriété |
Valeur |
| Name |
cmdClose |
| Caption |
&Fermer |
Double cliquez sur le bouton pour accéder, dans module de code,
à la procédure événementielle "Private Sub cmdClose_Click()" et
saisissez-y le code suivant (notez le "Option compare text")
|
Option Explicit
Option Compare Text
'---------------------------------
Private Sub cmdClose_Click()
'---------------------------------
Unload Me
End Sub
|
Vous devez obtenir un formulaire ayant l'aspect suivant :
Nous voici prêts pour étudier l'appel de ce formulaire frmCalc
depuis notre formulaire de menu (frmMenu) et voir comment se comportent les évènements
liés à cette manipulation.
Pour cela, commencez par saisir le code suivant dans le module
du formulaire frmCalc :
|
Option Explicit
Option Compare Text
Private Const Trace_Events = True
'-----------------------------------
Private Sub cmdClose_Click()
'-----------------------------------
Unload Me
End Sub
'-----------------------------------
Private Sub Form_Initialize()
'-----------------------------------
If Trace_Events Then
MsgBox "Form_Initialize",
vbInformation, "frmCalc"
End Sub
'-----------------------------------
Private Sub Form_Load()
'-----------------------------------
If Trace_Events Then MsgBox
"Form_Load", vbInformation, "frmCalc"
End Sub
'-----------------------------------
Private Sub Form_Paint()
'-----------------------------------
If Trace_Events Then Me.Print "Form_Paint"
End Sub
'-----------------------------------
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode
As Integer)
'-----------------------------------
If Trace_Events Then MsgBox
"Form_QueryUnload", vbInformation, "frmCalc"
End Sub
'-----------------------------------
Private Sub Form_Resize()
'-----------------------------------
If Trace_Events Then MsgBox
"Form_Resize", vbInformation, "frmCalc"
End Sub
'-----------------------------------
Private Sub Form_Unload(Cancel As Integer)
'-----------------------------------
If Trace_Events Then MsgBox
"Form_Unload", vbInformation, "frmCalc"
End Sub
|
Vous remarquerez l'utilisation d'une constante privée pour ce module
qui nous permettra d'activer ou de désactiver les messages pour les
événements (à la longue c'est pénible !).
Après avoir tapé (ou copié/collé) ce code dans le module (n'oubliez pas
que, pour créer une procédure événementielle, il faut et il suffit de sélectionner
l'objet dans la ComboBox de gauche, en haut de la fenêtre du module) et
l'événement dans la ComboBox de droite), pensez à sauvegarder votre travail
(disquette dans la barre d'outils).
Formulaire appelant :
Vous pouvez fermer le formulaire frmCalc et ré-ouvrir le formulaire frmMenu.
On ré-ouvre un formulaire existant en double cliquant sur son nom dans
l'explorateur de projet (Ctrl-R).
Ajoutez un bouton de commande pour lequel vous entrerez les valeurs de
propriétés suivantes :
| Propriété |
Valeur |
| Name |
cmdCalc |
| Caption |
Calculatrice |
Vous avez donc, maintenant, un menu qui a cet aspect :

Dans un premier temps, nous allons appeler le formulaire frmCalc
par la méthode la plus simple qui soit : en utilisant sa méthode Show sans aucun
paramètre. Tapez le code suivant pour l'événement Click du bouton cmdCalc :
|
'---------------------------------
Private Sub cmdCalc_Click()
'---------------------------------
frmCalc.Show
MsgBox "Après appel frmCalc dans frmMenu", vbInformation, "Test"
End Sub
|
Sauvez le projet et faites le test ... Utilisez Ctrl-F5 pour lancer le projet
afin de détecter d'éventuelles erreurs de syntaxe. Le menu apparaît et,
lorsque vous cliquez sur le bouton "Calculatrice" vous voyez apparaître
les différentes boites de dialogue (MsgBox) vous indiquant quels sont les
événements qui se déclenchent dans le formulaire appelé. Notez que pour
l'événement Paint, nous ne pouvions utiliser MsgBox(dans ce cas l'événement
Paint serait déclenché en boucle). Nous avons donc choisi d'écrire sur le
fond du formulaire (méthode Print) le nom de l'événement.
Vous voyez les messages pour les événements Initialize, Load,
Resize puis le formulaire s'affiche (permettant de vérifier que
l'événement Paint a bien eu lieu) et nous voyons le message envoyé par
l'appelant (frmMenu) "Après appel frmCalc dans frmMenu". Le
code appelant a chargé et affiché frmCalc puis a continué son exécution sans
attendre. Il est donc bien évident qu'il n'est pas possible, dans ces
conditions, de faire, à cet endroit, un traitement dépendant des saisies
faites par l'utilisateur dans le formulaire appelé. Pour cela, il aurait fallu
que VB attende la fermeture du formulaire appelé (frmCalc) pour continuer
l'exécution de son code. Nous verrons, dans peu de temps, qu'il y a une
solution simple à ce problème.
Ensuite, lorsque vous cliquez sur le bouton "Fermer" de la Calculatrice,
vous obtenez l'affichage des 2 messages correspondant aux événements "Form_Query_Unload"
et "Form_Unload" du formulaire.
Vous pouvez, dès maintenant, désactiver l'affichage des messages
d'événements en modifiant la valeur de la constante "Trace_Events"
pour la passer à "False". Notez que le message du formulaire
appelant (dans la Sub cmdCalc_Click), lui, reste actif. Nous en avons encore
besoin pour l'explication qui va suivre !
Fenêtre modale
Avez vous bien observé le comportement de votre formulaire appelé (frmCalc)
et du code exécuté dans l'appelant (frmMenu) ? Relancez l'exécution sans les
messages de trace des événements ... Notez que le formulaire appelé apparaît
et que le message provenant du code de l'appelant apparaît tout de suite par
dessus le formulaire appelé. De plus, vous pouvez, en cliquant dessus,
ré-activer le formulaire de menu. Vous pourriez même fermer le menu en
laissant le formulaire appelé ouvert.
Tout ça n'est pas très "carré" !
La solution à ces petits tracas est d'appeler le formulaire "frmCalc"
en mode Modal. A ce moment, seul le formulaire appelé sera actif, vous
ne pourrez plus cliquer sur le menu ou le fermer tant que vous n'aurez pas
fermé l'appelé.
Pour cela, modifiez comme suit le code de la procédure événementielle cmdCalc_Click()
dans le code du formulaire "frmMenu".
|
'---------------------------------
Private Sub cmdCalc_Click()
'---------------------------------
frmCalc.Show vbModal
MsgBox "Après appel frmCalc dans frmMenu",
vbInformation, "Test"
End Sub
|
Relancez le programme et notez les différences de comportement
: non seulement vous ne pouvez plus activer le menu tant que vous êtes sur le
formulaire appelé (frmCalc) mais, le message provenant du code source de
l'appelant n'apparaît qu'au moment où vous fermez l'appelé !!
Et, ça, c'est fondamental !
Voilà qui permet donc d'attendre que l'utilisateur ait rempli
puis validé le formulaire appelé avant de continuer le
traitement dans le formulaire appelant. La structure de vos logiciels va s'en
trouver grandement simplifiée (en attendant que vous maîtrisiez des
techniques plus sophistiquées).
Pour un développeur débutant, je conseille de ne faire QUE
des formulaires en mode modal. Cela pose de puissants garde-fous
contre d'éventuelles fausses manipulations de l'utilisateur et structure
automatiquement votre logiciel en forçant les appels de procédures à être séquentiels
rendant ainsi l'analyse plus simple.
Toutefois, dans l'état actuel des choses, il y a UN formulaire que vous ne
savez pas afficher en modal .... c'est le menu principal ! Comme ce n'est pas
votre code qui l'appelle, vous n'avez pas la main sur le mode d'appel. Rassurez
vous, il y a, bien sûr, une solution.
Cette solution consiste à modifier le point d'entrée du programme. Appelez
les propriétés du projet (menu "Projet / Propriétés de PForms").
Regardez le contenu de la liste "Objet de démarrage" (onglet
"Général"). Vous voyez que s'y trouvent vos deux formulaires mais
aussi une ligne "Sub Main". Vous allez sélectionner cette
ligne puis fermer ce dialogue par "OK".
En faisant cela vous avez demandé à VB de lancer votre projet en
commençant par le code source contenu dans une procédure publique nommée
"Sub Main". Comme, pour le moment, elle n'existe pas encore,
votre projet ne veut plus démarrer. Nous allons créer cette procédure afin de
remettre les choses en état.
Pour créer une procédure publique (accessible depuis l'ensemble du
code source de l'application) il faut, et il suffit, que la procédure soit une
"Public Sub" enregistrée dans un "module de base"
(.BAS). Ajoutez un module à votre projet en utilisant le menu "Projet /
Ajouter un module" et en sélectionnant le seul modèle disponible
"module". Appelez ensuite la fenêtre des propriétés afin de
lui donner un nom tout de suite. Name est la seule propriété disponible
pour un module : donnez lui, par exemple, le nom de "UtiGen"
pour "Utilitaires généraux".
Il ne vous reste plus qu'à saisir le code suivant (ici, pas de sélection
dans les ComboBox en haut de la fenêtre de module, en effet, le code que nous
écrivons maintenant n'est pas du code événementiel mais du code séquentiel,
déclenché par un appel explicite d'une autre portion de code).
|
Option Explicit
Option Compare Text
'---------------------------
Public Sub main()
'---------------------------
frmMenu.Show vbModal
End Sub
|
Ensuite, prenez le temps de sauvegarder l'ensemble du projet en
cliquant sur la disquette dans la barre d'outils. VB va vous demander un
répertoire et un nom pour le module que vous venez de créer. Acceptez le nom
par défaut (utigen.bas) mais faites bien attention que le répertoire
sélectionné soit bien celui du projet.
Conservez ce début de TD et prenez le temps de réviser les
leçons sur les messages utilisateur et la
déclaration
et l'utilisation des constantes et variables avant de continuer. Si ces
notions ne vous sont pas familières, lisez, sans faute,
la
page concernant l'utilisation des contrôles utilisateur.
Vous trouverez un lien sur la suite du TD1 à la fin de la page
traitant des contrôles. Si vous pensez maîtriser suffisamment ces
notions, utilisez le lien ci dessous pour accéder à la suite du TD.