VB6 - Boîtes de dialogue & communication inter-form

Publié 05 mai 08 11:31

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.

par Renfield
Classé sous : , , ,
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 :

Commentaires

# warning said on mai 5, 2008 13:44:

Cool, j'ai longtemps hésité à bloguer sur VB6, je vais pouvoir m'y mettre aussi ;)).

# Matthieu MEZIL said on mai 5, 2008 15:43:

Pour VB6, je ne sais pas mais pour VB.Net, perso je préfère utiliser des délégués. Tu peux passer un delegate à ta Form Form2 et après libre à tes formes utilisant Form2 (en modale) de mettre définir le délégué et, le cas échéant, de mettre le code que tu veux dedans (et donc propre à chaque form).

Sinon, si tes contrôles sont bindés, ils peuvent se raffraichir automatiquement.

# FREMYCOMPANY said on mai 5, 2008 19:33:

VB.NET :

=========

Oui, le binding (solution similaire à la Object proposée ici en fait) est pas mal dans de nombreux cas.

Sinon, en effet, les Delegates et les Events (ce qui finalement revient un peu au mêmeà c'est une solution assez fréquente aussi.

# Renfield said on mai 19, 2008 15:02:

Et pour un écran de verrouillage par password, par exemple :

Appelant (FrmMain)

...

If FrmPass.Launch =False Then

   Unload Me

   Exit Sub

End If

...

FrmPass:

Private mbDialogResult As Boolean

Public Function Launch() As Boolean

   mbDialogResult = False

Me.Show vbModal

   DoEvents

   If mbDialogResult Then

       If VERIFICATION_MOT_DE_PASSE(CcTxtPassword.Text) Then

           Launch = True

       End If

   End If

   Unload Me

End Function

Private CcBtnOk_Click()

   mbDialogResult = True

   Me.Hide

End Sub

Private CcBtnCancel_Click()

   Me.Hide

End Sub

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Tutoriaux EF par Matthieu MEZIL le il y a 32 minutes

- CodePlex : Seadragon AJAX Intellisense Helper par Blog technique de Nicolas Boonaert le il y a 1 heure et 27 minutes

- VS2008 et le message "Unable to start Debugging for [your exe]" par Jerome Laban le il y a 2 heures et 13 minutes

- SharePoint 2007 : Zones et URL internes par Arnault Nouvel le il y a 7 heures et 10 minutes

- .NET 4.0 / Silverlight 2 : changements brisants sur les types String et Char par CoqBlog le il y a 22 heures et 25 minutes

- Utiliser OpenCV sous DevC++ (options de compilation) par MadMatt le 11-21-2008, 19:35

- ZUNE : Nouvelle version du SoftWare et FirmWare – V 3.1 par Blog Technique de Romelard Fabrice le 11-21-2008, 15:15

- [Open XML] Les liens de la semaine 17/11/08 et autres infos en vrac par Julien Chable le 11-21-2008, 14:38

- TCB : Epicurien vous dites ? A Paris par The Mit's Blog le 11-21-2008, 10:39

- [Open XML] Les liens de la spécifications ISO par Julien Chable le 11-21-2008, 10:06




Ce blog

Abonnements