Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Question idiote sur Form_Unload

11 réponses
Avatar
Aski
Bonjour,

J'essaie de respecter scrupuleusement les instructions de la FAQ
http://faq.vb.free.fr/index.php?question=15
Je viens d'écrire un programme d'une seule feuille dans lequel tout arrêt tu
programme est demandé par Unload Me.
Form_Unload comprend la destruction des variables suivie d'un message
d'avertissement.
Très curieusement, Form_Unload se comporte comme une procédure quelconque.
Lorsqu'elle est exécutée, la suite du programme se poursuit.
Pour le moment j'ai ajouté End à la fin.
Aïe François pas taper. ;-)

Je suis très perplexe.
--
Cordialement
Aski

10 réponses

1 2
Avatar
parci
On Thu, 19 Jul 2007 20:05:47 +0200, "Aski" wrote:

Bonjour,

J'essaie de respecter scrupuleusement les instructions de la FAQ
http://faq.vb.free.fr/index.php?question
Je viens d'écrire un programme d'une seule feuille dans lequel tout arrêt tu
programme est demandé par Unload Me.
Form_Unload comprend la destruction des variables suivie d'un message
d'avertissement.
Très curieusement, Form_Unload se comporte comme une procédure quelconque.
Lorsqu'elle est exécutée, la suite du programme se poursuit.
Pour le moment j'ai ajouté End à la fin.
Aïe François pas taper. ;-)

Je suis très perplexe.



Sans voir le code, faut deviner ...

Tu dois probablement créer une nouvelle instance d'un objet sans t'en
rendre compte et perdre la référence existante. Exemple avec un Form
et un 2 CommandButton :

Private m_Form As Form

Private Sub Command1_Click()
Unload Me
End Sub

Private Sub Command2_Click()
Set m_Form = New Form1
End Sub

Private Sub Form_Unload(Cancel As Integer)
Set m_Form = Nothing
End Sub

Si il y a 2 click sur Command2, la première instance de Form1 créée
n'est plus référencer par aucune variable et elle reste en mémoire.


Ou en plus vicieux (avec un Form) :

Private m_Form As Form

Private m_Form As Form

Private Sub Form_Load()
Set m_Form = New Form1
End Sub

Private Sub Form_Unload(Cancel As Integer)
MsgBox m_Form.Name
Set m_Form = Nothing
End Sub

Une instance de Form1 est crée dans le Load mais cette instance n'est
pas réellement chargée car comme dit l'aide "Toute référence à une
feuille (sauf dans une instruction Set ou If...TypeOf) la charge
automatiquement si elle ne l'est pas déjà.".
L'appel d'une propriété (m_Form.Name) de cette instance déclenche le
chargement de l'objet (Load) et donc la création d'une deuxième
instance : la référence sur la première instance est perdue et elle
reste en mémoire.

Conclusion, vire le End et exécute en mode pas à pas pour voir ce qui
passe.
Avatar
Aski
Hello parci,

Tu as savamment écrit :

On Thu, 19 Jul 2007 20:05:47 +0200, "Aski" wrote:

Bonjour,

J'essaie de respecter scrupuleusement les instructions de la FAQ
http://faq.vb.free.fr/index.php?question
Je viens d'écrire un programme d'une seule feuille dans lequel tout
arrêt tu programme est demandé par Unload Me.
Form_Unload comprend la destruction des variables suivie d'un message
d'avertissement.
Très curieusement, Form_Unload se comporte comme une procédure
quelconque. Lorsqu'elle est exécutée, la suite du programme se
poursuit.
Pour le moment j'ai ajouté End à la fin.
Aïe François pas taper. ;-)

Je suis très perplexe.



Sans voir le code, faut deviner ...



Je veux bien le faire, mais c'est relativement long.

Tu dois probablement créer une nouvelle instance d'un objet sans t'en
rendre compte et perdre la référence existante. Exemple avec un Form
et un 2 CommandButton :



Je pensais aussi à des objets, mais aucun n'est créé dynamiquement.
Seul objet, un ListBox placé à la création sur la seule feuille du projet.

Conclusion, vire le End et exécute en mode pas à pas pour voir ce qui
passe.



C'est comme cela que j'ai procédé.

Je n'ai rien trouvé de mieux que de simplifier le programme au maximum, en
supprimant même la ListBox.
Le programme ne s'arrête pas puisqu'on atteint le derbier MsgBox de MainPgm.

Merci de t'interesser à mon cas

Aski

//////////////////////////////////////////////////////////////

Option Explicit

Private T() As String

Private Sub Form_Load()
Show
MainPgm
End Sub

Private Sub Form_Unload(Cancel As Integer)
Erase T
Close
MsgBox "Sortie du programme"
End Sub

Private Sub MainPgm()
Dim Auto As String
Dim Test As Boolean
Test = False: Auto = ""
If Auto <> "Auto" Then
If MsgBox("Répondre 'non'", vbYesNo) = vbNo Then
Test = True
Unload Me
End If
End If
MsgBox "Le programme n'aurait-il pas dû s'arrêter"
End Sub

//////////////////////////////////////////////////////////////
Avatar
LE TROLL
Bonjour,

J'ai testé ce que tu dis,
A priori
unload formX
n'est pas exécuté car la feuille a encore du code
et cancel est sans doute <> 0,
ça ne force donc pas la fermeture, d'où l'écriture
suivante:

Sub Command1_Click() ' bouton
Unload Form1
Exit Sub ' <<<------
MsgBox "on ne dervait pas voir ça"
End Sub

Sub Form_Unload(cancel As Integer)
MsgBox "ici procédure unload" & vbLf & cancel
Unload Form1 ' ici aussi si fermé par [X]
End
End Sub

--
Romans, logiciels, email, site personnel
http://irolog.free.fr/joe.htm
------------------------------------------------------------------------------------
"Aski" a écrit dans le message de
news: uab%
| Bonjour,
|
| J'essaie de respecter scrupuleusement les
instructions de la FAQ
| http://faq.vb.free.fr/index.php?question
| Je viens d'écrire un programme d'une seule
feuille dans lequel tout arrêt tu
| programme est demandé par Unload Me.
| Form_Unload comprend la destruction des
variables suivie d'un message
| d'avertissement.
| Très curieusement, Form_Unload se comporte comme
une procédure quelconque.
| Lorsqu'elle est exécutée, la suite du programme
se poursuit.
| Pour le moment j'ai ajouté End à la fin.
| Aïe François pas taper. ;-)
|
| Je suis très perplexe.
| --
| Cordialement
| Aski
|
Avatar
Aski
Hello LE TROLL,

Tu as savamment écrit :

Bonjour,

J'ai testé ce que tu dis,
A priori
unload formX
n'est pas exécuté car la feuille a encore du code
et cancel est sans doute <> 0,



Non j'ai essayé Cancel=0

ça ne force donc pas la fermeture, d'où l'écriture
suivante:

Sub Command1_Click() ' bouton
Unload Form1
Exit Sub ' <<<------
MsgBox "on ne dervait pas voir ça"
End Sub



C'est une solution mais est-ce LA solution ?

Sub Form_Unload(cancel As Integer)
MsgBox "ici procédure unload" & vbLf & cancel
Unload Form1 ' ici aussi si fermé par [X]
End
End Sub



End est interdit par François.
Avatar
Jacques93
Bonjour Aski,
Aski a écrit :
Bonjour,

J'essaie de respecter scrupuleusement les instructions de la FAQ
http://faq.vb.free.fr/index.php?question
Je viens d'écrire un programme d'une seule feuille dans lequel tout
arrêt tu programme est demandé par Unload Me.
Form_Unload comprend la destruction des variables suivie d'un message
d'avertissement.
Très curieusement, Form_Unload se comporte comme une procédure
quelconque. Lorsqu'elle est exécutée, la suite du programme se poursuit.
Pour le moment j'ai ajouté End à la fin.
Aïe François pas taper. ;-)

Je suis très perplexe.



Le problème vient du fait que tu appelles Unload Me dans la procédure
MainPgm, elle même appelée dans l'événement Load (qui n'est donc pas
terminé). M'est avis que l'on ne peut faire un Unload sur un objet dont
l'événement Load est en cours (ça devrait d'ailleurs, a mon avis,
générer une erreur comme quoi cette action n'est pas possible dans ce
contexte)

Une solution parmi d'autres est d'utiliser un module :

Option Explicit

Public Sub Main()
Form1.Show
Form1.MainPgm
Unload Form1
End Sub

et dans ton code de feuille :


Option Explicit

Private T() As String

Private Sub Form_Unload(Cancel As Integer)
Erase T
Close
MsgBox "Sortie du programme"
End Sub

Public Sub MainPgm()
Dim Auto As String
Dim Test As Boolean
Test = False: Auto = ""
If Auto <> "Auto" Then
If MsgBox("Répondre 'non'", vbYesNo) = vbNo Then
Test = True
Exit Sub ' à la place de Unload
End If
End If
MsgBox "Le programme n'aurait-il pas dû s'arrêter"
End Sub


Ne pas oublier de mettre l'objet de démarrage sur Sub Main au lieu de
Form1 dans les propriétés de ton programme.

A voir si tu peux adapter cette structure à ton projet ?

--
Cordialement,

Jacques.
Avatar
Aski
Hello Jacques,

Tu as savamment écrit :

Le problème vient du fait que tu appelles Unload Me dans la procédure
MainPgm, elle même appelée dans l'événement Load (qui n'est donc pas
terminé). M'est avis que l'on ne peut faire un Unload sur un objet
dont l'événement Load est en cours (ça devrait d'ailleurs, a mon avis,
générer une erreur comme quoi cette action n'est pas possible dans ce
contexte)

Une solution parmi d'autres est d'utiliser un module :



Je suis sûr que tu as vu juste. Je pensais à quelque chose dans ce genre
mais sans savoir vraiment cerner le bug.
Je n'ai jamais eu un tel problème, tout simplement parce que mes programmes
sont toujours assez volumineux et que je ne ne place pratiquement dans la
feuille de démarrage que les évènements de la feuille.
Je donnerai la solution, après avoir testé.

Merci
--
Henri
Avatar
LE TROLL
Re-bonjour,

Non, END n'est pas interdit par Microsoft,
François c'est pas Microsoft (pas encore).

Je crois que le problème est que END ne
décharge pas certains objet déclarés avec Set, ou
des objets logiques (peut être ?), mais s'il n'y a
pas tout ça, END est suffisant !

Personnellement je n'ai jamais constaté que
mes programmes tournaient après les avoir fermés
par END (ce que je faisais jadis directement),
puis, comme certains dirent que ça tournait
encore, ben je ferme désormais les feuilles
(Unload 1, 2, 3) + END.

A priori (déduction), Unload ne s'exécute
qu'une fois qu'il a terminé le code en cours, ou
qu'il rencontre un débranchement. On pourrait
aussi mettre LES unload dans la fonction du même
nom de la feuille maîtresse, et appeler la
procédure avec un truc du genre : call unload(x),
mais je ne sais absolument pas si ça marche ?

Je ne sais pas si c'est LA solution, mais
c'est une solution qui fonctionne en tout cas, en
plus, souvent il n'y a pas une solution, mais DES
solutions...

--
Romans, logiciels, email, site personnel
http://irolog.free.fr/joe.htm
------------------------------------------------------------------------------------
"Aski" a écrit dans le message de
news: OB9$
| Hello LE TROLL,
|
| Tu as savamment écrit :
|
| > Bonjour,
| >
| > J'ai testé ce que tu dis,
| > A priori
| > unload formX
| > n'est pas exécuté car la feuille a encore du
code
| > et cancel est sans doute <> 0,
|
| Non j'ai essayé Cancel=0
|
| > ça ne force donc pas la fermeture, d'où
l'écriture
| > suivante:
| >
| > Sub Command1_Click() ' bouton
| > Unload Form1
| > Exit Sub ' <<<------
| > MsgBox "on ne dervait pas voir ça"
| > End Sub
|
| C'est une solution mais est-ce LA solution ?
| >
| > Sub Form_Unload(cancel As Integer)
| > MsgBox "ici procédure unload" & vbLf & cancel
| > Unload Form1 ' ici aussi si fermé par [X]
| > End
| > End Sub
| >
| End est interdit par François.
|
Avatar
Aski
Hello LE TROLL,

Tu as savamment écrit :

Re-bonjour,

Non, END n'est pas interdit par Microsoft,
François c'est pas Microsoft (pas encore).

Je crois que le problème est que END ne
décharge pas certains objet déclarés avec Set, ou
des objets logiques (peut être ?), mais s'il n'y a
pas tout ça, END est suffisant !

Personnellement je n'ai jamais constaté que
mes programmes tournaient après les avoir fermés
par END (ce que je faisais jadis directement),
puis, comme certains dirent que ça tournait
encore, ben je ferme désormais les feuilles
(Unload 1, 2, 3) + END.

A priori (déduction), Unload ne s'exécute
qu'une fois qu'il a terminé le code en cours, ou
qu'il rencontre un débranchement. On pourrait
aussi mettre LES unload dans la fonction du même
nom de la feuille maîtresse, et appeler la
procédure avec un truc du genre : call unload(x),
mais je ne sais absolument pas si ça marche ?

Je ne sais pas si c'est LA solution, mais
c'est une solution qui fonctionne en tout cas, en
plus, souvent il n'y a pas une solution, mais DES
solutions...



Je considère qu'un programme doit être propre et conforme à certaines
règles, comme une lettre par courtoisie avec celui qui la lira.
J'essaie de m'améliorer et les qualités de la plupart des intervenants de ce
groupe m'y aident, qu'ils soient Microsoft ou non, MVP ou non.
Même avec mon Apple II j'essayais de faire aussi propre que possible et ce
n'était pas facile.
Avatar
Aski
Hello Jacques93 et LE TROLL,

Finalement, la méthode de Jacques est la seule qui fonctionne avec la
première de LE TROLL qui vient immédiatement à l'esprit si on veut éviter le
End.

Private Sub MainPgm()
Dim Auto As String
Dim Test As Boolean
Test = False: Auto = ""
If Auto <> "Auto" Then
If MsgBox("Répondre 'non'", vbYesNo) = vbNo Then
Test = True
Unload me
Exit Sub
End If
End If
MsgBox "Le programme n'aurait-il pas dû s'arrêter"
End Sub

Reste à savoir quelle est la méthode la mieux construite.
Avatar
Jean-marc
Aski wrote:
Hello Jacques93 et LE TROLL,

Finalement, la méthode de Jacques est la seule qui fonctionne avec la
première de LE TROLL qui vient immédiatement à l'esprit si on veut
éviter le End.

Private Sub MainPgm()
Dim Auto As String
Dim Test As Boolean
Test = False: Auto = ""
If Auto <> "Auto" Then
If MsgBox("Répondre 'non'", vbYesNo) = vbNo Then
Test = True
Unload me
Exit Sub
End If
End If
MsgBox "Le programme n'aurait-il pas dû s'arrêter"
End Sub

Reste à savoir quelle est la méthode la mieux construite.



Hello,

Jacques a donné la clef du problème: On ne doit
pas faire un unload dans un load. On peut toujours éviter par
construction de faire cela, et c'est LA seule solution propre.

Pour le reste, on peut bien sur toujours bricoler et trouver une
solution qui va "fonctionner", mais comme tu le dis, l'idée est
de faire le plus propre et correct possible, donc voila :-)

Bonne journée !

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
1 2