Accueil
Club Emploi Blogs   TV   Dév. Web PHP XML Python Autres 2D-3D-Jeux Sécurité Windows Linux PC Mac
Accueil Conception Java DotNET Visual Basic  C  C++ Delphi Eclipse MS-Office SQL & SGBD Oracle  4D  Business Intelligence

Cours VB.NET

Date de mise à jour : 05/12/2010


X-A. Démarrer, arrêter un programme : Sub Main(), fenêtre Splash
X-A-1. Démarrer par un formulaire
X-A-2. Démarrer par Sub Main()
X-A-3. Fenêtre Splash
X-A-4. Comment arrêter le programme ?
X-A-5. Fin de programme : Attention !
X-B. Ouvrir plusieurs formulaires
X-B-1. Créer un formulaire en VB 2003
X-B-2. Créer un formulaire en VB 2005
X-B-3. Formulaire modal ou non modal
X-B-4. Dénomination des formulaires après leur création
X-B-5. Autres remarques sur les formulaires
X-B-5-a. Un formulaire est un objet : On peut ajouter des méthodes et des membres à un formulaire
X-B-5-b. Exemple plus complet : Afficher un formulaire
X-B-5-c. Récupération d'informations par DialogResult
X-B-5-d. Bouton par défaut
X-C. Faire communiquer les formulaires
X-C-1. Comment, à partir du premier formulaire, consulter un objet du second formulaire ?
X-C-1-a. En VB 2003 2005 2008 si on instancie le formulaire
X-C-1-a-i. Première solution
X-C-1-a-ii. Seconde solution
X-C-1-a-iii. Troisième solution
X-C-1-a-iv. Quatrième solution
X-C-1-b. En VB 2005, sans instanciation de formulaire
X-C-2. Comment, à partir du formulaire 'secondaire', connaître le formulaire 'propriétaire' ?
X-C-3. Les formulaires ouverts à partir de VB 2005
X-C-4. Utilisation de DialogResult
X-D. Créer une fenêtre 'multi documents'
X-D-1. Comprendre les programmes MDI
X-D-2. En VB 2003
X-D-2-a. Création de la fenêtre conteneur parent
X-D-2-b. Création des fenêtres filles
X-D-2-c. Comment connaître la fenêtre fille active ?
X-D-2-d. Comment avoir accès aux objets de la fenêtre fille à partir du conteneur ?
X-D-2-e. Comment parcourir toutes les fenêtres filles ?
X-D-2-f. Comment fermer toutes les fenêtres enfants ?
X-D-2-g. Comment avoir accès aux objets du conteneur à partir de la fenêtre fille ?
X-D-2-h. Comment une routine du module conteneur appelle une routine dans la fenêtre fille active ?
X-D-2-i. Agencement des fenêtres filles
X-D-3. En VB 2005 2008


X-A. Démarrer, arrêter un programme : Sub Main(), fenêtre Splash

Quand vous démarrez votre programme, quelle partie du code va être exécutée en premier?

En Vb 2003

Vous pouvez le déterminer en cliquant sur le menu Projet puis Propriétés de NomduProjet, une fenêtre Page de propriétés du projet s'ouvre.

Sous la rubrique Objet du démarrage, il y a une zone de saisie avec liste déroulante permettant de choisir:

-Le nom d'un formulaire du projet

ou

-Sub Main()


A partir de Vb 2005 (Framework 2) :

Ouvrir le 'Projet Designer', il est directement accessible dans l'explorateur de solution (Double cliquer sur 'My Projet')ou par le menu Projet-> Propriétés de ..:

On définit:

Le Formulaire de démarrage (startUp Form).

Si 'Activer l'infrastructure de l'application' est coché, l'élément de démarrage ne peut être qu'un formulaire; s'il est décoché, on peut lancer le programme par la Sub Main().

Attention: ne pas confondre Formulaire de démarrage en haut et Ecran de démarrage (écran splash) en bas.



X-A-1. Démarrer par un formulaire

Si vous tapez le nom d'un formulaire du projet, c'est celui-ci qui démarre : cette fenêtre est chargée au lancement du programme et la procédure Form_Load de cette fenêtre est effectuée.

En théorie, si vous avez une application avec un formulaire, le fait de dessiner ce formulaire crée une Classe Form1; il faudrait donc théoriquement créer une instance de ce formulaire (par un Dim MyForm As New Form1) pour lancer l'application.

En pratique, dessinez un formulaire, lancez l'exécution, ça marche car le runtime crée une instance du formulaire automatiquement à l'aide de sa méthode New et l'affiche (sans que l'on ai besoin de l'intancier soit même).



X-A-2. Démarrer par Sub Main()

C'est cette procédure Sub Main qui s'exécute en premier lorsque le programme est lancé.

Elle peut servir à ouvrir le formulaire de démarrage:


Exemple 1:

En mode design Form1 a été dessinée, C'est un modèle 'une Classe'.

Dans un module standard, dans une Sub Main(), on instancie initForm à partir de la Class Form1. Puis on affiche ce formulaire (cette fenêtre) avec .ShowDialog

Sub Main()

        Dim initForm As New Form1

        initForm.ShowDialog()

End Sub

Exemple 2:

Sub Main() 
' Démarre l' application et affiche une instance de Form1
Application.Run(New Form1())
End Sub
S'il y a plusieurs threads, Application.Run commence à exécuter une boucle de messages d'application standard sur le thread en cours et affiche le formulaire spécifié. Peut être utilisé aussi s'il y a un seul thread.


warning Attention Sub Main() peut se trouver dans une Classe (Y compris une classe de formulaire) ou dans un module:
Si vous déclarez la procédure Main dans une classe, vous devez utiliser le mot clé Shared.

Class Form1

Public Shared Sub Main()

    .....

End Sub

..

End Classe
Dans un module, la procédure Main n'a pas besoin d'être partagée (Shared).

Module1

Sub Main()

...

End Sub

End Module

Fonction Main():

On peut utiliser 'Function Main' (au lieu de 'Sub Main') qui retourne un Integer, que le système d'exploitation utilise comme code de sortie du programme. D'autres programmes peuvent tester ce code en examinant la valeur ERRORLEVEL Windows.

Function Main() As Integer
...
Return 0 ' Zéro signifie : tout est Ok.
End Function

Récupération de la ligne de commande:

Main peut également avoir comme argument un tableau de String. Chaque élément du tableau contient un des arguments de ligne de commande utilisée pour appeler le programme. Vous pouvez réaliser diverses actions en fonction de leurs valeurs.

Function Main(ByVal CmdArgs() As String) As Integer
...

Return 0 
End Function

On rappelle qu'en VB2005, si 'Activer l'infrastructure de l'application' est coché dans les propriétés du programme, le formulaire de démarrage ne peut être qu'un formulaire; s'il est décoché, on peut lancer le programme par la Sub Main().


Autre méthode de récupération de la ligne de commande en VB 2005:

On trouve les arguments de la ligne de commande dans My.Application.CommandLineArgs (VB 2005)

Exemple:

Cliquez sur un fichier de données, l'exécutable lié s'exécute et ouvre le fichier de données.

(Exemple: Quand on clique sur un fichier .bmp on lance automatiquement Paint qui charge l'image .bmp)

Il faut que l'extension du fichier soit liée avec le programme exécutable, si vous cliquez sur le fichier de données, cela lance l'exécutable.

Modifier l'extension liée Explorer->Outils-> Option des dossiers-> Type de fichiers

Dans Form_Load mettre:

If My.Application.CommandLineArgs.ToString <> "" Then

Dim i

For i = 0 To My.Application.CommandLineArgs.Count - 1

If mid(My.Application.CommandLineArgs(i).ToString,1,2)  "-o" Then 
' dans le cas ou la ligne de commande contient le nom du fichier à lancer et '-o'

FileName = Mid(My.Application.CommandLineArgs(i).ToString, 3)

OpenFile() ' charger les données

Exit For

End If

Next

End If


X-A-3. Fenêtre Splash

C'est une fenêtre qui s'ouvre au démarrage d'un programme, qui montre simplement une belle image, (pendant ce temps le programme peut éventuellement initialiser des données, ouvrir des fichiers...) ensuite la fenêtre 'Splash' disparaît et la fenêtre principale apparaît.


En Vb 2003 (Framework 1) il faut tout écrire:

Dans la Sub Main il est possible de gérer une fenêtre Splash.

Exemple:

Je dessine Form1 qui est la fenêtre Spash.

Dans Form2 qui est la fenêtre principale, j'ajoute:

Public Shared Sub Main()

Dim FrmSplash As New Form1    'instance la fenêtre Splash 

Dim FrmPrincipal As New Form2 'instance la feuille principale

FrmSplash.ShowDialog()        'affiche la fenêtre Splash en Modale


FrmPrincipal.ShowDialog()     'a la fermeture de Splash,  affiche la fenêtre principale

End Sub
Dans Form1 (la fenêtre Splash)

Private Sub Form1_Activated

Me.Refresh() 'pour afficher totalement la fenêtre.

'ici ou on fait plein de choses on ouvre des fichiers ou on perd du temps.

' s'il n'y a rien a faire on met un Timer pour que l'utilisateur admire la belle image.

Me.Close()

End Sub
On affiche FrmSplash un moment (Ho! la belle image) puis on l'efface et on affiche la fenêtre principale. Word, Excel.. font comme cela.


Autre méthode:

Public Sub main() 


'création des formulaires frmmain and frmsplash avec le designer 

Dim frmsplash As New frmsplash 

Dim frmmain As New frmmain 

 

'on affiche la Splash

frmsplash.Show() 

Application.DoEvents() 

 

'On attend (3000 milliseconds) 

System.Threading.Thread.Sleep(3000) 

 

'On efface la Splash

frmsplash.Close() 

 

'On affiche le formulaire principal

Application.Run(frmmain)  

 

End Sub 

En Vb 2005 (Framework 2) c'est très simple:

Ouvrir le 'Projet Designer', il est directement accessible dans l'explorateur de solution (My Projet)ou par le menu Projet-> Propriétés de..:

Il faut que 'Activer l'infrastructure de l'application' soit coché:

On définit

Le formulaire de démarrage (startUp Form),

L'écran de démarrage (Splash Screen), il suffit d'indiquer son nom (En mode Run, VB l'affiche et le fait disparaître quand le formulaire de démarrage s'ouvre).


On peut aussi ajouter un écran splash tout fait:

Menu Projet, Ajouter un formulaire Windows, double cliquer sur 'formulaire de démarrage'.

On obtient:

Le nom de l'application, la version, le nom de la société sont automatiquement mis à jour en utilisant les 'Informations de l'assembly' accessible par un bouton situé dans le projet designer, en face du nom du formulaire de démarrage.

L'inconvénient de cet écran Splash automatique est qu'il s'affiche et s'efface très rapidement, avant de charger le formulaire de démarrage!! Pour le voir une seconde, j'ai ajouté à la fin de la procédure Form_Load de cet écran:

Me.Show()

Application.DoEvents()

System.Threading.Thread.Sleep(1000)

Autre solution: utiliser My.Application.MinimumSplashScreenDisplayTime, qui determine le temps d'affichage en ms. J'ai eu du mal à trouver où mettre l'instruction (dans le formulaire Splash ou Application_StartUp cela ne fonctionne pas!!
il faut mettre la ligne dans Application New (propriété du projet, onglet application, bouton 'Afficher les évènements de l'application", Liste déroulante à gauche 'MyApplication', liste déroulante à droite 'New'); rajouter la derniere ligne du code ci dessous.

Partial Friend Class MyApplication
        
        <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _
        Public Sub New()
            MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.AuthenticationMode.Windows)
            Me.IsSingleInstance = false
            Me.EnableVisualStyles = true
            Me.SaveMySettingsOnExit = true
            Me.ShutDownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses
        End Sub
        
        <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _
        Protected Overrides Sub OnCreateMainForm()
            Me.MainForm = Global.WindowsApplication1.Form1
        End Sub
        
        <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _
        Protected Overrides Sub OnCreateSplashScreen()
            Me.SplashScreen = Global.WindowsApplication1.SplashScreen1
            My.Application.MinimumSplashScreenDisplayTime = 2000 '<= A rajouter
        End Sub
    End Class

X-A-4. Comment arrêter le programme ?


Me.Close()    'Ferme la fenêtre en cours
Noter bien Me désigne le formulaire, la fenêtre en cours.

Application.Exit()    'Ferme l'application
Vide la 'pompe à messages', ferme les formulaires. Si des fichiers sont encore ouvert, cela les ferme. (Il vaut mieux les fermer avant, intentionnellement.)


On peut aussi utiliser l'instruction End.



X-A-5. Fin de programme : Attention !

Outre l'usage de Application.Exit(), on peut terminer une application en fermant les formulaires, mais:

Dans Visual Basic 6.0, une application ne se terminait que lorsque tous les objets créés étaient détruits.

Dans Visual Basic .NET 2003, l'application se termine lorsque l'objet de démarrage est détruit. Si le formulaire que vous fermez est le formulaire de démarrage de votre application, votre application se termine. Si la procédure Sub_Main est définie comme objet de démarrage l'application se termine dès que le code de Sub_Main a fini de s'exécuter.

Depuis VB 2005 vous avez le choix entre les 2 solutions: terminer l'application quand le formulaire de démarrage est fermé ou quand tous les formulaires sont fermés.(dans l'application Designer voir 'Mode d'arrêt')



X-B. Ouvrir plusieurs formulaires

Comment à partir d'un formulaire 'Form1' ouvrir un second formulaire à partir de la Classe 'Form2' ?


Voici le plan du chapitre:

-En VB2003

-En VB 2005

-Formulaire modal et non modale.

-Comment se nomment les formulaires?

-Autres

-Un formulaire est un objet

-Exemple

-DialogResult

-Bouton par défaut



X-B-1. Créer un formulaire en VB 2003

A- Il faut d'abord créer la Classe Form2

Ajoutez un formulaire (Menu Projet, Ajouter un formulaire au projet), nommez le 'Form2' .

On se rend compte que quand on ajoute un formulaire (Form2 par exemple), on crée une nouvelle 'classe':

'Class Form2' qui hérite de System.Windows.Forms.Form , elle hérite donc de toutes les propriétés et méthodes de la Classe Form qui est la classe 'formulaire'.

Public Class Form2

Inherits System.Windows.Forms.Form 

End Class
Elle contient du code généré automatiquement par le concepteur Windows Forms et les procédures liées aux évènements.

Dessinez dans Form2 les contrôles nécessaires.

B- Il faut créer ensuite le nouvel Objet formulaire, une instance de Form2:

Pour créer un nouveau formulaire dans le programme, il faut:
  • Instancier un formulaire à partir du moule, de la Classe Form2 avec le mot New.
  • Ouvrir ce formulaire, le faire apparaître, (avec ShowDialog, c'est un formulaire modal)

Dim formSecondaire As New Form2()

formSecondaire.ShowDialog()  
En résumé: on a Form1, on dessine Form2:

Pour que le bouton nommé "Créer Form secondaire" ouvre le second formulaire, il faut y mettre le code:

Private ButtonCreerFormSecondaire_Click()

  Dim formSecondaire As New Form2()

  formSecondaire.ShowDialog()  

End Sub
info En conclusion:
Le fait d'ajouter un formulaire à un projet crée une Class, (un 'type' de formulaire, un moule) ce qui permet ensuite d'instancier (de créer) un objet formulaire.
VB 2003 est tolérant pour le premier formulaire: si on dessine un formulaire et ses contrôles et qu'on lance le programme, il accepte de fonctionner bien qu'on ait pas instancié le formulaire. Par contre, si on crée une seconde classe formulaire, il faut créer une instance de ce formulaire.

Dim formSecondaire As New Form2()
formSecondaire.ShowDialog()  


X-B-2. Créer un formulaire en VB 2005

Pas besoin d'instancier systématiquement un formulaire:

On peut utiliser la Class Form2 sans instancier, en utilisant directement le nom de la Classe:

On dessine Form2 (la classe) puis on peut écrire directement:

Private ButtonCreerFormSecondaire_Click()
    Form2.ShowDialog()
End sub
On peut même utiliser les propriétés directement:

 Form2.ForeColor = System.Drawing.Color.Coral
 Form2.BackColor = System.Drawing.Color.Cyan
En fait, comme il n'y a pas d'instance de Form2, VB en crée une.

On peut aussi faire comme en VB 2003 en instancier le formulaire, mais c'est plus complexe.



X-B-3. Formulaire modal ou non modal

Un formulaire modal est un formulaire qui, une fois ouvert, prend la main, interdit l'usage des autres fenêtres. Pour poursuivre, on ne peut que sortir de ce formulaire.

Exemple typique: une MessageBox est un formulaire modal, les fenêtres d'avertissement dans Windows sont aussi modales.

Pour ouvrir un formulaire modal, il faut utiliser la méthode .ShowDialog

Dim f As New Form2           

f.ShowDialog()
ou en VB 2005

form2.ShowDialog()
Noter, et c'est très important, que le code qui suit .showDialog est exécuté après la fermeture de la fenêtre modale.


Pour avoir un formulaire non modal faire:

Dim f As New Form2      

f.Show() 
ou en VB 2005

form2.Show()
Dans ce cas le formulaire f s'ouvre, le code qui suit .Show est exécuté immédiatement, et il est possible de passer dans une autre fenêtre de l'application sans fermer f.


Instance multiple: si un bouton1 contient le code:

Private Button1_Click

Dim f As New Form2      

f.Show()      

End Sub
A chaque fois que l'on clique sur le bouton cela ouvre un formulaire: on peut en ouvrir plusieurs. On se retrouve avec X instances de Form2!!

Pour éviter cela:
  • Utiliser ShowDialog
  • Mettre Dim f As New Form2 dans la partie déclaration, ainsi il n'y aura qu'une instance de Form2. Le second click déclenche une erreur.

Class Form1

Dim f As New Form2   

 

Private Button1_Click   

    f.Show()      

End Sub

End Class


X-B-4. Dénomination des formulaires après leur création

En VB 2003 et 2005 (avec instanciation d'un formulaire).

Une procédure qui est dans Form1 crée un formulaire par:

Class Form1
Private Buttonformsecondaire_Click ()    

    Dim formSecondaire As New Form2

End Sub
End Class
  • Dans le formulaire formSecondaire créé:
    Utiliser Me pour désigner le formulaire où on se trouve. (Form2 ou formSecondaire ne sont pas acceptés)

    Exemple:

    Me.Text= "Second formulaire" modifie le texte de la barre supérieure du formulaire

    Le formulaire formSecondaire pourra être fermé par Me.close() dans le code du bouton Quitter par exemple.


  • Hors du formulaire formSecondaire, dans la procédure où a été instancié le formulaire:
    Utiliser formSecondaire pour désigner le formulaire.

    Exemple:

    Si la fenêtre appelante veut récupérer des informations dans le formulaire formSecondaire (un texte dans txtMessage par exemple), il faudra écrire.

    Text=formSecondaire.txtMessage.Text

  • Par contre, hors de la procédure qui a créée le formulaire, formSecondaire n'est pas accessible car on a crée le formulaire dans une procédure: cette instance du formulaire n'est visible que dans cette procédure. Pour rendre un formulaire accessible partout on peut écrire Public formSecondaire As New Form2 dans la zone générale avant les procédures.

Class Form1
Public formSecondaire As New Form2
Private Buttonformsecondaire_Click ()    

    

End Sub
End Class
Exemple:

Class Form1

 

Sub MaRoutine()

    Dim formSecondaire As New Form2

    Text=formSecondaire.TextBox.Text

End Sub

 

Sub AutreRoutine()

..

End Sub

 

End Class
Dans la procédure MaRoutine() le formulaire formSecondaire est visible et formSecondaire.TextBox est utilisable, pas dans la procédure AutreRoutine(). En résumé: Attention donc, si vous instanciez un formulaire dans une procédure, elle sera visible et accessible uniquement dans cette procédure.


Cela parait évident car un formulaire est un objet comme un autre et sa visibilité obéit aux règles habituelles ( J'ai mis malgré tout un certains temps à le comprendre!!).

info Un formulaire est un objet et sa visibilité obéit aux règles habituelles: Il peut être instancié dans une procédure, un module, précédé de 'Public' ,'Private'.. ce qui permet de gérer son accessibilité.

En VB 2005, sans instanciation des formulaires:

Par contre en VB 2005, si vous dessinez Form2 et que vous tapez:

Private ButtonCreerFormSecondaire_Click()
    Form2.Show()
End sub
Vous pouvez utiliser dans Form1 les propriétés et contrôles de Form2 directement:

 Form2.ForeColor = System.Drawing.Color.Coral
 
La Classe Form2 étant public , on a toujours accès au formulaire et aux contrôles.

(Par contre, on n'a pas accès aux procédures évènements qui sont 'Private')


Un exemple:

Dans Form1 Button1 affiche le formulaire Form2 (directement sans instanciation).

Dans la procédure Button2_Click de Form1 on a accès au TextBox qui est dans Form2:



X-B-5. Autres remarques sur les formulaires


X-B-5-a. Un formulaire est un objet : On peut ajouter des méthodes et des membres à un formulaire

On a vu que, en fait, il y a création d'une Classe quand on dessine un formulaire, et bien comme dans un module de Classe (on verra cela plus loin), on peut ajouter des propriétés et des méthodes.

Pour ajouter une méthode à un formulaire, il faut créer une Sub Public dans le corps de la fenêtre:

Class Form1

Public Sub Imprime()

    Code d'impression

End Sub

End Class
Si une instance de la fenêtre se nomme F, F.Imprime() exécute la méthode Imprime (donc la sub Imprime())


De même, pour définir un membre d'un formulaire, il faut ajouter une variable 'public'.

Public Utilisateur As String
Permet d'utiliser en dehors du formulaire F.Utilisateur


X-B-5-b. Exemple plus complet : Afficher un formulaire

Comment savoir si un formulaire existe, s'il n'existe pas le créer, s'il existe le rendre visible et lui donner la main :

        If f Is Nothing Then    'Si f=rien 

            f = New Form2

            f.ShowDialog()

        Else

            If f.Visible = False Then

                f.Visible = True

            End If

            f.Activate()

        End If
Autre solution plus complète gérant aussi la taille du formulaire:

Si le formulaire existe et n'a pas été 'disposed'(détruit), le mettre à la taille normale et en avant.

        If Not IsNothing(F) Then
            'Si on en a pas déjà disposé
            If Not F.IsDisposed Then
                F.WindowState = FormWindowState.Normal  ' Optional
                F.BringToFront()  '  Optional
            Else
                F = New Form3
                F.Show()
            End If
        Else
            F = New Form3
            F.Show()
        End If
(Merci Michel de Montréal)



X-B-5-c. Récupération d'informations par DialogResult

On ouvre un formulaire modal, comment, après sa fermeture, récupérer des informations sur ce qui s'est passé dans ce formulaire modale?

Par exemple, l'utilisateur a t-il cliqué sur le bouton Ok ou le bouton Cancel pour fermer le formulaire modale?

Pour cela on va utiliser une propriété DialogResult des boutons, y mettre une valeur correspondant au bouton, quand l'utilisateur clique sur un bouton, la valeur de la propriété DialogResult du bouton est assignée à la propriété DialogResult du formulaire, on récupère cette valeur à la fermeture du formulaire modal.

Dans le formulaire modal Form2 on met

 ButtonOk.DialogResult= DialogResult.ok

 

 ButtonCancel.DialogResult= DialogResult.Cancel
Dans le formulaire qui appelle:

Form2.ShowDialog()

If form2.DialogResult= DialogResult.ok then

    'l'utilisateur a cliqué sur le bouton ok

End if
Remarque:
  1. On utilise comme valeur de DialogResult les constantes de l'énumération DialogResult:DialogResult.ok .Cancel .No .Yes .Retry .None .Abort .Ignore.
  2. Si l'utilisateur clique sur la fermeture du formulaire modal (bouton avec X) cela retourne DialogResult.cancel
  3. on peut aussi utiliser la syntaxe: If form2.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK Then qui permet en une seule ligne d'ouvrir form2 et de tester si l'utilisateur a cliqué sur le bouton ok de form2.
  4. La fermeture du formulaire modal par le bouton de fermeture ou l'appel de la méthode Close ne détruit pas toujours le formulaire modal, il faut dans ce cas utiliser la méthode Dispose pour le détruire.


X-B-5-d. Bouton par défaut

Parfois dans un formulaire, l'utilisateur doit pouvoir, valider (taper sur la touche 'Entrée') pour accepter et quitter rapidement le formulaire (c'est l'équivalent du bouton 'Ok') ou taper 'Echap' pour sortir du formulaire sans accepter (c'est l'équivalent du bouton 'Cancel').

Il suffit pour cela de donner aux propriétés AcceptButton et CancelButton du formulaire,le nom des boutons ok et cancel qui sont sur la feuille.

form1.AcceptButton = buttonOk
form1.CancelButton = buttonCancel
Si l'utilisateur tape la touche 'Echap' la procédure buttonCancel_Click est exécutée.



X-C. Faire communiquer les formulaires

Rappel:Formulaire=fenêtre
Rappel:Formulaire=fenêtre
Comment faire communiquer 2 formulaires?+++
  1. Comment à partir d'un formulaire consulter un objet d'un autre formulaire?
  2. Comment à partir du second formulaire connaître le formulaire propriétaire?
  3. Les formulaires ouverts en VB 2005
Cette question est fréquemment posée et créée beaucoup de problèmes!!


X-C-1. Comment, à partir du premier formulaire, consulter un objet du second formulaire ?

Un premier formulaire en ouvre un second, dans le second saisir un texte, puis l'afficher dans le premier.


X-C-1-a. En VB 2003 2005 2008 si on instancie le formulaire

Reprenons toujours le même exemple: le premier formulaire (Class Form1) crée une instance de Form2 (L'utilisateur du programme clique sur ButtonCreerformsecondaire de Form1) cela crée formSecondaire. formSecondaire contient un textbox nommé TextBox2. L'utilisateur saisit un texte dans le textbox2 et quitte formsecondaire. Comment Form1 peut-il récupérer TextBox2.text et l'afficher dans un label1.

La Class Form1 contient un Button1 "Créer Form2" et contient un Label1.


La Class Form2 aura une instance: formsecondaire, elle contient TextBox2 et un Button2 "Quitter".



X-C-1-a-i. Première solution
Pour qu'un formulaire puisse utiliser les objets d'un autre formulaire, il faut que le second formulaire soit visible.

Créer un formulaire formSecondaire en utilisant la Classe Form2.

Class Form1

Sub buttonCreerformsecondaire_Click

  Dim formSecondaire As New form2 ()    'On crée formSecondaire

  formSecondaire.ShowDialog()           'On ouvre formSecondaire

  label1.Text=formSecondaire.TextBox2.Text 'On récupère le texte de TextBox1

End Sub

 

End Class
formSecondaire n'est visible QUE dans button1_Click+++

Les contrôles de Form2 sont Public ce qui permet d'y avoir accès.

On peut se poser la question de savoir si après ShowDialog le formulaire modal formSecondaire existe encore?

La ruse c'est de mettre dans le code du bouton Quitter de Form2 Me.Hide() pour rendre la fenêtre Form2 invisible mais accessible (et pas Me.Close() qui détruirait la fenêtre, le contrôle txtMessage et son contenu).

Dim formSecondaireAs New Form2()

formSecondaire.ShowDialog()

label1.Text=formSecondaire.TextBox2.Text

formSecondaire.Close()

Une fois que le texte à été récupéré, on fait disparaître le formulaire formSecondaire.

En réalité, curieusement, il semble que les propriétés de formSecondaire soient accessibles même après un Close!! Cela vient du fait que, bien que le formulaire soit fermé, il n'est pas encore détruit.


Si vous voulez créer un formulaire Form2 qui soit visible dans la totalité d'un formulaire Form1, il faut l'instancier dans la partie déclaration du formulaire Form1:

Class Form1

    Public formSecondaire As New Form2()

    

Sub buttoncreerformsecondaire_Click

  formSecondaire.ShowDialog()           'On ouvre formSecondaire

  label1.Text=formSecondaire.TextBox2.Text 'On récupère le texte de TextBox1

End Sub
    

End Class
On peut ainsi l'ouvrir par formSecondaire.ShowDialog() dans une procédure et lire une zone texte dans une autre procédure.



X-C-1-a-ii. Seconde solution
Si vous voulez créer un formulaire qui soit visible dans la totalité du programme et dont les contrôles ou propriétés soient accessibles par l'ensemble du programme, il faut l'instancier dans un module standard (Les puristes vont pas aimer!!):

Module MonModule

    Public formSecondaire As New Form2().

End Module




Class Form3

Sub Buttoncreerformsecondaire_Click

    formSecondaire.ShowDialog()
    'ou MonModule.formSecondaire.ShowDialog()
End Sub

 

Sub Button2_Click

    label1.Text= formSecondaire.TextBox2.Text

End Sub

 


End Class
On peut avoir accès au TextBox2 n'importe ou!!

C'est un objet 'Public' et on n'aime pas bien!!!



X-C-1-a-iii. Troisième solution
On peut créer dans le second formulaire un objet Public Shared:

Class Form2

Public Shared MonTextBox As TextBox

Private Sub Button2_Click 'Bouton quitter

MonTextBox = TextBox1    'On affecte à l'objet MonTexBox le TextBox1

Me.Close()

End Sub

End Class
Dans Form1

Class Form1

Sub buttoncreerformsecondaire_Click

Dim formSecondaire As New form2 ()    'On crée formSecondaire

formsecondaire.ShowDialog()

Label1.Text = formsecondaire.MonTextBox.Text()

End Sub

End Class
Noter que contrairement aux exemples donnés par certains sites, il faut bien écrire: formsecondaire.MonTextBox.Text() et pas Form2.MonTextBox.Text() du moins en VS 2003.

Cette troisième solution a le même principe que la première, en plus compliqué!!

On peut simplement retenir que si formsecondaire est visible, seuls ses membres publiques sont visibles bien entendu: par exemple ses propriétés, ses contrôles, les procédures publiques, PAS les procédures événementielles qui sont privées.

Dans le même ordre d'idée, on peut créer une Property Public:

Class Form2

Public ReadOnly Property LeText() As String
    Get
        Return TextBox2.Text
    End Get
End Property
End Class

Class Form1

Sub button1_Click

Dim formSecondaire As New form2 ()    'On crée formSecondaire

formsecondaire.ShowDialog()

Label1.Text = formsecondaire.LeText   'On utilise la property

End Sub

End Class
Même conclusion, mais il faut toujours utiliser formsecondaire qui doit être visible , c'est ça l'important!!



X-C-1-a-iv. Quatrième solution
Créer une variable ou une Classe 'Public' (dite 'Globale') et y faire transiter les données :

Module MonModule

    Public BAL As String     'Variable Public dite 'Boite aux lettres'

End Module

Class Form2

Private Sub Button2_Click 'Bouton quitter

BAL = TextBox2.Text    'On met TextBox1.Text dans BAL

Me.Close()

End Sub

End Class

 

Class Form1

Sub Button1_Click

    formSecondaire.ShowDialog()

    label1.Text= BAL    'On récupère ce qui est dans BAL

End Sub

 

End Class
Cela a tous les inconvénients: c'est une variable globale, source d'erreur, n'importe quel formulaire peut écrire dans BAL...
C'est très mal de faire cela.
Mais c'est simple et cela marche bien.



X-C-1-b. En VB 2005, sans instanciation de formulaire

Par contre en VB 2005, si vous dessinez Form2 et que vous tapez:

Private ButtonCreerFormSecondaire_Click()
    Form2.Show()
End sub
Vous pouvez utiliser dans Form1 les propriétés et contrôles de Form2 directement:

 Label1.Text = Form2.TextBox2.Text
La Classe Form2 étant public , on a toujours accès au formulaire et aux contrôles.

(Par contre, on n'a pas accès aux procédures évènements qui sont 'Private'; on peut d'ailleurs les mettre 'Public' pour y avoir accès)



X-C-2. Comment, à partir du formulaire 'secondaire', connaître le formulaire 'propriétaire' ?

Exemple : Comment savoir quel formulaire a ouvert le formulaire en cours ?

ShowDialog possède un argument facultatif, owner, qu'on peut utiliser afin de spécifier une relation 'propriétaire'-'formulaire en cours'. Par exemple, lorsque le code de votre formulaire principal ouvre un formulaire, vous pouvez passer Me comme propriétaire de la boîte de dialogue, afin de désigner votre formulaire principal comme propriétaire, comme le montre le code de l'exemple suivant :

Dans Form1

Dim formSecondaire As New Form2 

f.ShowDialog(Me)
Dans Form2
On peut récupérer le nom du 'propriétaire', qui a ouvert la fenêtre.
Il est dans Owner,et on peut par exemple afficher son nom.

Par exemple:

    Label1.text=Me.Owner.ToString
Cela affiche: NomApplication.NomFormulaire,Texte de la barre de titre.

Owner a toutes les propriétés (Name, Location, Controls..) d'un formulaire car il hérite de Form. , mais on ne peut pas consulter les contrôles de Owner directement. Il faut d'abord caster owner qui est une Form en Form1, ensuite on peut avoir accès aux contrôles de Form1.

Dim f As Form1 = CType(Me.Owner, Form1)

Label1.Text() = f.Button1.Text

Comment obtenir le nom du formulaire propriétaire? Autre méthode.

Une autre méthode consiste à surcharger le constructeur de la Form2 afin qu'il accepte un paramètre qui indique le propriétaire ( nom de l'instance de Form1):

Dans Form1: Lors de l'instanciation de la form2 il faut écrire:

Dim FormSecondaire As New Form2(Me) 
FormSecondaire .ShowDialog(Me) 'affichage modal de la form2
Dans Form2:

 Private FormProp As Form1
    Public Sub New(ByVal NomForm As Form1) 
        MyBase.New() 
        FormProp = NomForm 
        
        InitializeComponent() 

    End Sub
On crée donc dans Form2 une variable FormProp qui indique la form propriétaire.

Pour appeler une méthode de form1 à partir de FormSecondaire (Form2):

FormProp.MaRoutine()

L'inconvénient de toutes ces méthodes est qu'il faut connaître la classe du formulaire propriétaire (Form1 ici).


X-C-3. Les formulaires ouverts à partir de VB 2005

- My.Application.OpenForms contient les formulaires ouverts.

Afficher le texte contenu dans la barre de titre du formulaire nommé 'Form3'.

MyTextBox.Text= My.Application.OpenForms("Form3")
Afficher le texte contenu dans la barre de titre du premier formulaire ouvert.

MyTextBox.Text= My.Application.OpenForms(0)

Exemple: rajouter le texte 'ouvert' à la barre de tache des formulaires ouverts:

For Each F As System.Windows.Forms.Form In My.Application.OpenForms
F.Text += "[ouvert]"
Next

- My.Forms contient tous les formulaires.

Afficher le texte contenu dans la barre de titre du formulaire Form1.

MyTextBox.Text= My.Forms.Form1.Text
Remarquons qu'il est interdit d'utiliser My.Forms.Form1 si on est dans Form1 .(il faut utiliser Me)


-Différence avec My.Application.OpenForms(0)?

Dim f As New Form1

f.Text = "hello"

f.Show()

TextBox1.Text = My.Forms.Form1.Text 
 
Affiche 'Form1' qui est le texte de la barre par défaut en design (celui de la Classe Form1).


TextBox2.Text = My.Application.OpenForms("Form1").Text    

'Affiche 'hello' qui est le texte de l'instance f


X-C-4. Utilisation de DialogResult

Si un formulaire Form1 ouvre un formulaire modal nommé Dialog1, il y a un moyen élégant pour le formulaire Form1 de récupérer une information du formulaire Dialog1 quans ce dernier est fermé (il est modal).

Dans le formulaire modal Dialog1, si l'utilisateur clique sur le bouton Ok, on met

 Sub ButtonOk_Click
 ButtonOk.DialogResult= DialogResult.ok
End Sub
Dans Form1 on a:

'On ouvre le formulaire Dialog1
Dialog1.ShowDialog()

If Dialog1.DialogResult= DialogResult.Ok then

    'l'utilisateur a cliqué sur le bouton ok

End if

Les seules valeurs possibles pour DialogResult sont Ok, Cancel, Yes, No, None, Abort, Ignore, Retry. On ne peut malheureusement pas utiliser une autre valeur


X-D. Créer une fenêtre 'multi documents'

Comment créer un programme MDI (Multi Document Interface) en VB 2003 puis en VB 2005 ?


X-D-1. Comprendre les programmes MDI

L'exemple de Word : la fenêtre principale (fenêtre MDI) contient les menus en haut, on peut ouvrir plusieurs documents dans des fenêtres filles.

Ci dessous l'exemple de LDF (Programme de comptabilité écrit par l'auteur):

On a une fenêtre MDI (conteneur) contenant 2 fenêtres filles affichant chacune une année de comptabilité.

Dans VB.NET, un MDIForm (fenêtre principale MDI) est une fenêtre quelconque dont la propriété :

IsMDIContainer = True.

Dans la fenêtre fille, la propriété MDIParent indique le conteneur (C'est à dire le nom de la fenêtre MDI) .


Les applications MDI peuvent avoir plusieurs conteneurs MDI.

Une fenêtre principale MDI peut contenir plusieurs fenêtres filles de même type ou de type différente.



X-D-2. En VB 2003


X-D-2-a. Création de la fenêtre conteneur parent

Exemple d'un programme MDI.

On va créer une Form1 qui est le conteneur.

Une Form2 qui est la fenêtre fille.

Dans Form1 le menu principal contient la ligne '&Nouvelle' qui crée une nouvelle instance de la fenêtre fille.

Créer la fenêtre Form1 :

Dans la fenêtre Propriétés, affectez la valeur True à la propriété IsMDIContainer. Ce faisant, vous désignez la fenêtre comme le conteneur MDI des fenêtres enfants.

Remarque: Affecter la valeur Maximized à la propriété WindowState, car il est plus facile de manipuler des fenêtres MDI enfants lorsque le formulaire parent est grand. Sachez par ailleurs que le formulaire MDI parent prend la couleur système (définie dans le Panneau de configuration Windows).

Ajouter les menus du conteneur :

A partir de la boîte à outils, faire glisser un contrôle MainMenu sur le formulaire. Créer un élément de menu de niveau supérieur en définissant la propriété Text avec la valeur &File et des éléments de sous-menu appelés &Nouvelle et &Close. Créer également un élément de menu de niveau supérieur appelé &Fenêtre.

Dans la liste déroulante située en haut de la fenêtre Propriétés, sélectionnez l'élément de menu correspondant à l'élément &Fenêtre et affectez la valeur true à la propriété MdiList. Vous activez ainsi le menu Fenêtre qui permet de tenir à jour une liste des fenêtres MDI enfants ouvertes et indique à l'utilisateur par une coche la fenêtre enfant active.

Il est conseillé de créer un module standard qui contient une procédure Main qui affiche la fenêtre principale:

Module StandartGénéral

Public FrmMDI as Form1

Sub Main()

    FrmMDI.ShowDialog()

End sub

End Module
Noter bien que FrmMDI est donc la fenêtre conteneur et est Public donc accessible à tous.



X-D-2-b. Création des fenêtres filles

Pour créer une fenêtre fille, il suffit de donner à la propriété MDIParent d'une fenêtre le nom de la fenêtre conteneur.

Dessiner dans Form2 les objets nécessaire dans la fenêtre fille.

Comment créer une instance de la fenêtre fille à chaque fois que l'utilisateur clique sur le menu '&Nouvelle'?

En premier lieu, déclarez dans le haut du formulaire Form1 (accessible dans tout le formulaire) une variable nommée MDIFilleActive de type 'Form2' qui contient la fenêtre fille active.

Dim MDIFilleActive As Form2
La routine correspondant au MenuItem &Nouvelle (dans la fenêtre MDI) doit créer une instance de la fenêtre fille :

Protected Sub MDIChildNouvelle_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 
_Handles MenuItem2.Click

   MDIFilleActive = New Form2()

   'Indique à la fenêtre fille son 'parent'.

   MDIFilleActive.MdiParent = Me

   'Affiche la fenêtre fille

   MDIFilleActive.Show()

End Sub
Ainsi l'utilisateur peut ouvrir plusieurs fenêtres filles.



X-D-2-c. Comment connaître la fenêtre fille active ?

Quand on en a ouvert plusieurs?

La fenêtre fille active est dans Me.ActiveMdiChild du conteneur

Comment voir s'il existe une fenêtre active?

If Not Me.ActiveMdiChild Is Nothing then    'elle existe
En mettant dans la variable MDIFilleActive la fenêtre active, on est sûr de l'avoir toujours à disposition: pour cela dans la procédure Form1_MdiActivate de la fenêtre MDI (qui se produit à chaque fois que l'on rentre dans la fenêtre fille avec la souris, le menu..) je récupère Me.ActiveMdiChild qui retourne la fenêtre fille active.


Dans Form1:

Private Sub Form1_MdiChildActivate..

    MDIFilleActive=Me.ActiveMdiChild

End Sub
warning Il faut comprendre que peut importe le nom de la fenêtre fille active, on sait simplement que la fenêtre fille active est dans MIDFilleActive, variable que l'on utilise pour travailler sur cette fenêtre fille.


X-D-2-d. Comment avoir accès aux objets de la fenêtre fille à partir du conteneur ?

De la fenêtre conteneur j'ai accès aux objets de la fenêtre fille par l'intermédiaire de la variable MDIFilleActive précédemment mise à jour; par exemple le texte d'un label:

 MDIFilleActive.label1.text

Comment avoir accès à des éléments de cette fenêtre fille, une sub Affichetotaux par exemple à partir de ActiveMdiChild:

Si je tape Me.ActiveMdiChild.AfficheTotaux cela plante!! (car ActiveMdiChild est une instance de la classe Form).

Il faut écrire: CType(ActiveMdiChild, Form2).Affichetotaux() (car il faut convertir ActiveMdiChild en classe Form2)



X-D-2-e. Comment parcourir toutes les fenêtres filles ?

La collection MdiChildren contient toutes les fenêtres filles, on peut les parcourir:

Dim ff As Form2

For Each ff In Me.MdiChildren

...

Next
Cela est valable s'il n'y a qu'un type de formulaire permettant de créer des formulaires enfants (Form2 par exemple)

Mais si on a 2 formulaires Form2 et Form3 cela se complique.

dim i_form as Form ' on utilise une variable Form :formulaire 

dim i_form3 as form3
dim i_form2 as form2

For Each i_form  In Me.mdichildren
    if typeof  i_form is form2 then
        i_form2 = ctype(i_form,form2)
        msgbox i_form2.property_du_form2
    end if

if typeof  i_form is form3 then
        i_form1 = ctype(i_form,form3)
        msgbox i_form3.property_du_form3
    end if
next
Merci Gaël.



X-D-2-f. Comment fermer toutes les fenêtres enfants ?


Dim form As Form

For Each form In Me.MdiChildren

form.Close()

Next


X-D-2-g. Comment avoir accès aux objets du conteneur à partir de la fenêtre fille ?

En utilisant Me.MdiParent qui contient le nom du conteneur.

Dans la fenêtre fille le code Me.MdiParent.text ="Document 1" affichera 'Document 1' dans la barre de titre du conteneur.



X-D-2-h. Comment une routine du module conteneur appelle une routine dans la fenêtre fille active ?

Si une routine public de la fenêtre fille se nomme Affiche, on peut l'appeler par:

MDIFilleActive.Affiche()
Il n'est pas possible d'appeler les évènements liés aux objets de la fenêtre fille, par contre la routine Affiche() dans notre exemple peut le faire.



X-D-2-i. Agencement des fenêtres filles

La propriété LayoutMdi de la fenêtre conteneur modifie l'agencement des fenêtres filles.

0 - MdiLayout.Cascade
1 - MdiLayout.TileHorizontal
2 - MdiLayout.TileVertical
3 - MdiLayout.ArrangeIcons


Exemple:

Le menu Item Cascade met les fenêtres filles en cascade.

Protected Sub CascadeWindows_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

   Me.LayoutMdi(System.Windows.Forms.MdiLayout.Cascade)

End Sub


X-D-3. En VB 2005 2008

90% du travail est fait automatiquement: c'est merveilleux!!

Dans l'explorateur de solution: Click droit sur le nom du programme ('mdi' ici):

Dans le menu, passer par 'Ajouter' puis 'Formulaire Windows':

Cliquer sur 'MDI Parent Form' ('Formulaire Parent MDI')

On obtient un formulaire MDI parent avec les menus, la barre d'icône, d'état, les menus déroutants avec image:

(Le logiciel a rajouté les 4 outils en bas, nécessaire pour réaliser l'interface.)

Le code qui génère les formulaires enfants est automatiquement crée:

Public Class MDIParent1

Private Sub ShowNewForm(ByVal sender As Object, ByVal e As EventArgs) Handles NewToolStripMenuItem.Click, 
	_NewToolStripButton.Click, NewWindowToolStripMenuItem.Click

' Créer une nouvelle instance du formulaire enfant.

Dim ChildForm As New System.Windows.Forms.Form

' Make it a child of this MDI form before showing it.

ChildForm.MdiParent = Me

m_ChildFormNumber += 1

ChildForm.Text = "Window " & m_ChildFormNumber

ChildForm.Show()

End Sub

Private Sub ExitToolsStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) 
_Handles ExitToolStripMenuItem.Click

'Quitter l'application

Global.System.Windows.Forms.Application.Exit()

End Sub

Private Sub CascadeToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) 
_Handles CascadeToolStripMenuItem.Click

'Positionnement des formulaires enfant

Me.LayoutMdi(MdiLayout.Cascade)

End Sub

Private Sub TileVerticleToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) 
_Handles TileVerticalToolStripMenuItem.Click

Me.LayoutMdi(MdiLayout.TileVertical)

End Sub

Private Sub TileHorizontalToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) 
_Handles TileHorizontalToolStripMenuItem.Click

Me.LayoutMdi(MdiLayout.TileHorizontal)

End Sub

Private Sub ArrangeIconsToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) 
_Handles ArrangeIconsToolStripMenuItem.Click

Me.LayoutMdi(MdiLayout.ArrangeIcons)

End Sub

Private Sub CloseAllToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) 
_Handles CloseAllToolStripMenuItem.Click

' Ferme tous les formulaires enfant

For Each ChildForm As Form In Me.MdiChildren

ChildForm.Close()

Next

End Sub

Private m_ChildFormNumber As Integer = 0

End Class

 

Les sources présentés sur cette page sont libres de droits, et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright © . Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.

Vos questions techniques : forum d'entraide Accueil - Publiez vos articles, tutoriels, cours et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones. Nous contacter - Copyright 2000..2005 www.developpez.com