VB6 - Boîtes de dialogue & communication inter-form
Bonjour,
Aujourd'hui, petit article (légèrement) technique.
Vous bourrez vos Forms de contrôles et prônez le tout-en-une-seule-form ? passez votre chemin ! (ou jetez un oeil à la suite)...
Pour les autres, sans plus tarder... voici le topo :
Vous avez une Form traitant, par exemple, d'une facture. Elle liste les différents paramètres de celle-ci.
Cette facture peut être liée à un client donné. La Form dispose par exemple d'une zone indiquant l'ID et le nom du client. Cette zone est adjointe d'un bouton qui permet d'afficher la liste des clients contenus dans la base de données.
Un double-clic sur l'un de ces clients, ou une pression sur le classique bouton "OK" de ma deuxième Form va mettre à jour ma Form facture.
Ca vous reviens ? Vous vous êtes sans doute retrouvés de nombreuses fois dans une situation de ce genre, n'est-ce pas ?
Ce qui m'interesse ici, c'est le process de communication entre ma facture (Form1) et ma liste de clients (Form2). Bien sur, il est conseillé de donner des noms plus parlants aux Forms.
J'ai lancé sur VbFrance deux appels à suggestion,
http://www.vbfrance.com/codes/BESOIN-SUGGESTIONS_46502.aspx et http://www.vbfrance.com/infomsg_BESOIN-SUGGESTIONS-CODE_1122798.aspx
Je remercie toutes les personnes qui ont participé.
Je vais maintenant discuter des diverses solutions qui s'offrent à nous.
- L'affichage d'un Form modale
Chacun aura je pense eu le reflex de se dire "me faut une Form modale !".
Et cela s'y prête tout à fait... Petit rappel: une form modale est une form qui prend le focus de l'application. Impossible de faire quoi que ce soit d'autre avec toute autre form, tant que me fenêtre modale est visible. Le cours normal de l'éxecution du code est même interrompu au niveau du "Form2.Show vbModal" tant que Form2 est visible. Les MsgBox me paraissent le plus simple exemple de fenêtre modale.
On évitera donc les boucles farfelues, et on ne masquera pas non plus Form1.
- Super simple, on peut tout manipuler...
dans Form1:
Private Sub CcBtnClientID_Click() Form2.CcTxtClientID.Text = Form1.CcTxtClientID.Text Form2.Show vbModal End Sub
et dans Form2:
Private Sub CcBtnOK_Click() Form1.CcTxtClientID.Text = Form2.CcTxtClientID.Text Unload Me End Sub
|
| By Renfield |
ayé, ca fonctionne ^^ Simplissime au possible... oui, mais plutôt maladroit.
En effet, il n'est jamais bon de manipuler les contrôles sis sur d'autres Forms.
Imaginez que plus tard, lors du développement de notre application de gestion, vous désiriez réutiliser Form2, depuis une autre Form. Vous pourriez par exemple lier des bons de commande à vos clients, ou réaliser ce que bon vous semble. Il vous faudra ajouter des tests (Select Case, j'imagine) afin que notre Form2 modifie tantôt Form1.CcTxtClientID.Text, tantôt Form3.CcTxtClientID.Text ...
Donc, coté réutilisabilité et maintenance, ce code ne convient pas du tout.
- Variables globales
Dans le même esprit, on peut passer par des variables globales et déclarer:
Public mnClientID As Long
dans un module standard, et communiquer par ce biai.
Cette variable publique sera néanmoins accessible depuis toutes les forms, toutes les modules, vous avez alors interêt a bien documenter la chose pour savoir qu'il faut utiliser cette variable. Se basant sur le même principe, vous allez sûrement ajouter toutes les variables qui permettent ce genre de communication, avec toutes les forms possibles. Ca peut être jugé suffisant, pour de petits projets, mais ça devient rapidement l'anarchie dans la liste intellisense.
- Objets indépendants
On s'approche doucement vers cette notion d'indépendance qui est à mon avis essentielle dans le design de vos Classes, UserControls et Forms (coté code, hein, je ne parle pas de look).
En effet, "chacun son job". La Form2 sert à afficher les clients, permettre d'en séléctionner un. Point barre. On n'a pas à s'y soucier de ce que l'appelant souhaite faire du résultat...
Bête astuce plutôt que révolution, je vais vous indiquer la manière de faire que j'ai mise au point, et que j'utilise dans divers projets professionnels (comprenant parfois des dizaines de Forms). L'idée est simplement de passer ses parametres à une méthode publique de Form2. Cette méhode "Launch" renvoie True si on a validé Form2 (et donc que le résultat obtenu est exploitable).
Vous trouverez le code détaillé ici: http://www.vbfrance.com/codes/BESOIN-SUGGESTIONS_46502.aspx
En voici quelques extraits:
Form1:
Private Sub CcBtnClient_Click() Dim nClientID As Long '# On récupère l'ID du client éventuellement lié a notre facture. nClientID = Val(CcTxtClient.Text) '# On lance Form2, qui va s'occuper de nous afficher la liste des clients. If Form2.Launch(nClientID) Then '# Et si l'on a validé la fenetre... '# On récupère le nom du Client. On pourrait en fait transmettre le Nom dans la méthode Launch de Form2 '# Mais non... pensez "réutilisabilité"... '# Une autre Form utilisant Form2 aura peut etre besoin de l'adresse, du numéro de téléphone du client, etc. '# On ne va pas ajouter quinze parametres à Launch. '# On se contente donc de transmettre l'ID, les informations souhaitées sont ensuite simplement extraites de '# la base de données End If End Sub
Form2: Private mbDialogResult As Boolean
'# Ici, l'ID client est en lecture-écriture, ce qui permet à l'appelant de donner l'ID du client précédant '# et de recevoir (si la fonction renvoie vrai), le nouvel ID. Public Function Launch(ByRef vnClientID As Long) As Boolean If PopulateList Then [...] Else '# Pas de client MsgBox "Aucun client.", vbInformation '# Et on quitte Exit Function End If '# Valeur par défault du "code retour" mbDialogResult = False '# Alignée à gauche, cette ligne de code est une vraie charnière dans l'execution. '# au dessus, l'initialisation, en dessous, la post-validation Me.Show vbModal '# Permet de masquer illico la fenetre, sans délai. Utile si la post-validation est longue... DoEvents '# On renvoie vrai ou faux, selon si on a valider ou non la fenêtre Launch = mbDialogResult '# Et si on valide... If Launch Then '# Pour cette Form, on renvoie l'ID [...] End If '# On décharge véritablement la Form Unload Me End Function
'# Si l'on presse Ok Private Sub CcBtnOk_Click() mbDialogResult = True Me.Hide End Sub
|
| By Renfield |
A noter que les éventuels tests de validité de saisie seront à effectuer dans CcBtnOk_Click, et non dans le post processing de Launch.
Réutilisabilité: il suffit d'appeler notre méthode Launch depuis la Form de notre choix, pour récuperer l'ID du client séléctionné dans la liste qui s'affichera.
Maintenabilité: chaque Form pourra avoir un traitement qui lui est propre de l'ID récupéré. Pas de référence aux contrôles de telle ou telle Form. Les éléments de communication nécessaires à l'utilisation de Form2 se trouvent dans Form2. On peut également utiliser des propriétés (Public Property Get/Let) ou des variables publiques que l'on placera dans Form2. Le tout étant de prendre garde de ne pas y mentionner de contrôle de Form2 (sous peine de déclencher le chargement de celle-ci).
Je conclurais en disant que chacun ses préférences, sa manière de coder, etc. J'ai vous ai simplement exposé ma façon de faire. A vous d'en tirer vos conclusions. Merci à tous, et bravo à ceux qui ont lu jusqu'au bout.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :