solilog
Messages postés273Date d'inscriptionsamedi 13 juin 2009StatutMembreDernière intervention18 avril 2015
-
11 juil. 2009 à 08:47
thierrybo
Messages postés15Date d'inscriptionlundi 16 juin 2003StatutMembreDernière intervention12 novembre 2010
-
9 oct. 2010 à 17:14
Bonjour à tous,
Comment savoir si une fenêtre est créée / affichées, je m'explique:
Quand je crée une fenêtre avec
form1 := tform1.create(self) - self étant une fenêtre parent, je crée ma fenêtre bien
si dans mon code je teste assigned(form1) , j'aurai True, bien.
si dans l'évenement OnClose de Form1 il y a Action : = cafree pour détruire la fenêtre, celle-ci sera détruite, mais la valeur du pointeur Form1 ne sera pas mise à nil, et dans ce cas, si je teste assigned(Form1) j'aurai True alors que la fenetre n'existe plus. En fait la procedure free détruit l'objet et libère l'expace mais ne met pas le pointeur à nil.
En fait, je veux enabler/disabler des actions (boutons, menus, ...) dans une forme si d'autres forms sont présentes (Action1.enabled := True/False), mais comment être sûr que les fenetres sont présentes assigned(xxx) peut me retourner une valeur fausse.
Une solution serait de renseigner une variabl dans form1.create : form1_aff = true et dans form1.destroy : form1_aff=false, et je pourrais faire action1.enabled := not form1_aff, ... et ainsi de suite pour les autres forms, mais ce n'est pas très élégant.
L'autre solution serait de boucler sur toutes les forms de l'application, ça ne me plait pas non-plus.
Avez-vous une idée ?
Bonne journée à tous.
thierrybo
Messages postés15Date d'inscriptionlundi 16 juin 2003StatutMembreDernière intervention12 novembre 20101 9 oct. 2010 à 17:14
Solilog nous disait le dimanche 12 juillet 2009 à 18:17:37
Bonjour,
Je dois être pinailleur,désolé.
Oui ça marche parce que tu forces Form2:= nil dans TForm2.FormClose ce que je veux éviter car "en théorie" c'est interdit de mettre un pointeur de classe à nil avant la fin des traitements (le close doit ensuite appeler free, destroy pour libérer la mem) et ça risque de ne pas ou de mal libérer la mem. Peut-être que je pinaille.
Bonjour,
désolé de remonter un vieux topic, mais comme je suis en apprentissage de l'organisation des fenêtres dans Delphi et que j'ai résolu mon problème justement en forçant Form2 à nil, j'en parle ici. Mon appli n'utilise que des fenêtres non modales, chaque form ne pouvant avoir qu'une seule instance et ne pouvant pas survivre à son parent.
Dans le livre "Mastering Delphi 7" de Marco Cantu, voici ce qu'il indique pour gérer des fenêtres non modales à instance unique où utilise justement cette technique, Mastering Delphi 7 > Part I: Foundations > Chapter 7: Working with Forms > Dialog Boxes and Other Secondary Forms, paragraphe "Creating Single-Instance Secondary Forms" :
The situation is a little more complex when you want to display only one copy of a modeless form. You have to create the form, if it is not already available, and then show it:
if not Assigned (Form2) then
Form2 : = TForm2.Create (Application);
Form2.Show;
With this code, the form is created the first time it is required and then is kept in memory, visible on the screen or hidden from view. To avoid using up memory and system resources unnecessarily, you'll want to destroy the secondary form when it is closed. You can do that by writing a handler for the OnClose event:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
// important: set pointer to nil!
Form2 := nil; end;
Notice that after you destroy the form, the global Form2 variable is set to nil, which contradicts the rule set earlier for forms with multiple instances, but as this is a single-instance we are in the exact opposite case. Without this code, closing the form would destroy its object, but the Form2 variable would still refer to the original memory location.
solilog
Messages postés273Date d'inscriptionsamedi 13 juin 2009StatutMembreDernière intervention18 avril 201510 11 juil. 2009 à 15:13
Merci à tous les deux mais ça ne m'aide pas car:
- Cirec - je ne veux pas utiliser xxx.Free ni xxx.FreeAndNil, je reste sur un close pour les forms et le close automatique pour les modals, (tu m'as quand même appris le freeandnill que je ne connaissait pas, merci)
- cantador - je fais ton test et button1.enabled est false malgré que Form2 soit détruite. assigned(form2) retourne true et form2.visible aussi.
procedure TForm1.Button2Click(Sender: TObject);
begin
form2:=tForm2.create(self);
form2.show;
// normalement le close est dans une autre proc
// mais pour le test c'est pareil
// je précise qu'il y a "Action:=caFree"
// dans form2.onclose
form2.close;
if assigned(form2) then
button1.enabled := not form2.visible;
end;
En plus il est possible que ça plante, car propriétés d'un objet détruit peuvent taper n'importe où en mem ...
Je vais mettre une variable dans chaque unit concernées genre Form1_vis : boolean, mise à true dans onCreate et false dans onclose, c'est moche mais au moins ça marche.
Si qq'1 a mieux à me proposer ...
Tcho à tous.
solilog
Vous n’avez pas trouvé la réponse que vous recherchez ?
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 11 juil. 2009 à 15:18
dans la fiche parent :
type
TFormParent = class(TForm)
procedure FormCreate(Sender: TObject);
private
fFormChild : TForm;
public
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
end;
var
FormParent: TFormParent;
implementation
procedure TFormParent.FormCreate(Sender: TObject);
begin
fFormChild := TForm.Create(Self);
fFormChild.FreeNotification(Self);
end;
procedure TFormParent.Notification(AComponent: TComponent; Operation: TOperation);
begin if (AComponent fFormChild) and (Operation OpRemove) then
fFormChild := nil
else
inherited;
end;
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 11 juil. 2009 à 15:45
ou encore :
type
TFormParent = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
fFormChilds : TList;
public
function RegisterFormChild(AFormChild: TForm): integer;
function UnregisterFormChild(AFormChild: TForm): integer;
end;
var
FormParent: TFormParent;
implementation
{$R *.dfm}
procedure TFormParent.FormCreate(Sender: TObject);
begin
fFormChilds := TList.Create;
end;
procedure TFormParent.FormDestroy(Sender: TObject);
var N : integer;
begin
for N := fFormChilds.Count-1 downto 0 do
RemoveFreeNotification(TForm(fFormChilds.Items[N]));
fFormChilds.Free;
end;
function TFormParent.RegisterFormChild(AFormChild: TForm): integer;
begin
result := fFormChilds.IndexOf(pointer(AFormChild));
if result = -1 then
begin
result := fFormChilds.Add(pointer(AFormChild));
FreeNotification(AFormChild);
end;
end;
function TFormParent.UnregisterFormChild(AFormChild: TForm): integer;
begin
result := fFormChilds.IndexOf(pointer(AFormChild));
if result <> -1 then
begin
RemoveFreeNotification(AFormChild);
fFormChilds.Delete(result);
end;
end;
cs_cantador
Messages postés4720Date d'inscriptiondimanche 26 février 2006StatutModérateurDernière intervention31 juillet 202113 11 juil. 2009 à 18:04
- cantador - je fais ton test et button1.enabled est false malgré que Form2 soit détruite. assigned(form2) retourne true et form2.visible aussi.
ce n'est pas possible...
si form2 est détruite (et son pointeur à nil) et que tu testes
solilog
Messages postés273Date d'inscriptionsamedi 13 juin 2009StatutMembreDernière intervention18 avril 201510 11 juil. 2009 à 19:53
Non cantador, c'est parce que button1créer.
La réponse de .enabled := Assigned(form2) retourne toujours True si Form2 a été une fois une fois créée.
La réponse de [../auteur/F0XI/360948.aspx f0xi] est la bonne, quoique lourde pour enabled sur des actions.
Mais je ne vois rien d'autre.
Problème clos, mous.
solilog
solilog
Messages postés273Date d'inscriptionsamedi 13 juin 2009StatutMembreDernière intervention18 avril 201510 11 juil. 2009 à 19:59
Non cantador, c'est parce que button .enabled := Assigned(form2) retourne toujours True si Form2 a été une fois une fois créée.
La réponse de [../auteur/F0XI/360948.aspx f0xi] est bonne, quoique lourde pour enabler des actions.
Mais je ne vois rien d'autre.
Problème clos, Tcho
solilog
solilog
Messages postés273Date d'inscriptionsamedi 13 juin 2009StatutMembreDernière intervention18 avril 201510 12 juil. 2009 à 18:17
Bonjour,
Je dois être pinailleur,désolé.
Oui ça marche parce que tu forces Form2:=nil dans TForm2.FormClose ce que je veux éviter car "en théorie" c'est interdit de mettre un pointeur de classe à nil avant la fin des traitements (le close doit ensuite appeler free, destroy pour libérer la mem) et ça risque de ne pas ou de mal libérer la mem. Peut-être que je pinaille.
Il eut été plus logique que Delphi mette à nil un pointezr libéré. Y a sans doute une raison.
C'est bon, j'ai utilisé des variables que je mets à true / false dans les create/close. des Forn2. Y aussi f0xi qui m'a aussi appris un truc pas mal (quoique un peu lourd pour des bouutons).
Au problème suivant.
solilog
cs_cantador
Messages postés4720Date d'inscriptiondimanche 26 février 2006StatutModérateurDernière intervention31 juillet 202113 13 juil. 2009 à 12:05
"en théorie" c'est interdit de mettre un pointeur de classe à nil avant la fin des traitements (le close doit ensuite appeler free, destroy pour libérer la mem) et ça risque de ne pas ou de mal libérer la mem. Peut-être que je pinaille.
Non je ne pense pas que cela pose des soucis,
mais effectivement, la mémoire est-elle libérée dans ce cas ?
solilog
Messages postés273Date d'inscriptionsamedi 13 juin 2009StatutMembreDernière intervention18 avril 201510 13 juil. 2009 à 17:10
Merci Cirec,
C'est le bon endroit pour mettre Form3:=nil dans la proc notification. T'es uns star.
Tcho.
Ps: C'est quoi l'histoire des fuites ? Si c'est une vanne, laissez tomber.