IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Libération de la mémoire du MDIChild


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2013
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Albanie

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2013
    Messages : 75
    Par défaut Libération de la mémoire du MDIChild
    salut
    j'ai un form1 MDIForm
    et form2 et form3 son MDIChild
    et j'ai :
    bouton2 pour afficher la form form2
    bouton3 pour afficher la form form3
    bouton1 pour fermer et libérer l'espace mémoire de tous les MDIChild
    Je veux libérer et fermer complètement l'espace mémoire de tous les MDIChild
    Quand j'appuie sur le bouton1 les MDIChild sont fermer
    Mais quand j'appuie à nouveau sur le bouton2 ou bouton3 le message(la form2 est active) est afficher donc les MDIChild sont restés "Assigned"
    Quelle est la solution pour les MDIChild ne restez pas "Assigned" Quand ils sont fermés ???
    voila le code du bouton2:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    procedure Tform1.Button2Click(Sender: TObject);
    begin
    if Not Assigned(form2) then
    begin
       Application.CreateForm(Tform2, form2);
       form2.Show;
    end
    else
       showmessage('la form2 est active');
    end;
    voila le code du bouton3:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure Tform1.Button3Click(Sender: TObject);
    begin
    if Not Assigned(form3) then
    begin
       Application.CreateForm(Tform3, form3);
       form3.Show;
    end
    else
       showmessage('la form3 est active');
    end;
    le code de l'evenement onClose de la form2:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure Tform2.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    Action := caFree;
    end;
    le code de l'evenement onClose de la form3:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure Tform3.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    Action := caFree;
    end;
    voila le code du bouton1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure Tform1.Button1Click(Sender: TObject);
    var i:integer;
    begin
    for i := MDIChildCount - 1 downto 0 do
    begin
    MDIChildren[i].Close;
    MDIChildren[i].Free;
    MDIChildren[i].Release;
    end;
    end;

  2. #2
    Membre Expert
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 544
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 70
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 544
    Billets dans le blog
    10
    Par défaut
    Voici un exemple. Tu peux utiliser plusieurs fois Button1Click. Disponible pour plus d'explications
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    ...
      SlListeFiches : TStringList ;
    ...
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Application.CreateForm(TForm2, Form2);
      SlListeFiches.Add(intToStr(integer(pointer(form2)))) ;
      Form2.Caption := intTostr(SlListeFiches.count-1) ;
      Form2.Show
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    var
      i1 : integer ;
      maFiche : TForm2 ;
    begin
      for i1 := 0 to SlListeFiches.Count -1 do
      begin
        maFiche := pointer(integer(strToInt(SlListeFiches[i1]))) ;
        FreeAndNil(maFiche) ;
      end;
      SlListeFiches.Clear
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      SlListeFiches := TStringList.Create ;
    end;

  3. #3
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 493
    Par défaut
    salut


    si tu veut n'ouvrir qu'une seul fois ta fenetre
    et tout fermer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    procedure TfMain.OpenUniqueFenettre2(Sender: TObject);
    var
      count : integer;
      i : integer;
      found : boolean;
    begin
      count := Pred(MDIChildCount);
      found := False;
      if   MDIChildCount > 0 Then
      begin
        i := 0;
        while (i <= count) and Not(found) do
        begin
           if  MDIChildren[i] is Tform2 Then
           begin
             found := true;
             Tform2(MDIChildren[i]).Show;
           end;
          Application.ProcessMessages;
          inc(i);
        end;
      end;
      if not(found) Then
        Tform2.create(Self);
    end;
    //////////////////////
     
    procedure TfMain.Toutfermer1Click(Sender: TObject);
    var
      i : integer;
      count : integer;
    begin
      count := MDIChildCount -1;
      if   MDIChildCount > 0 Then
        for i := count downTo 0 Do
        begin
          Tform(MDIChildren[i]).close; // ne pas oublier de type l'objet
          Application.ProcessMessages;
        end;
    end;

  4. #4
    Membre actif
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2013
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Albanie

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2013
    Messages : 75
    Par défaut
    merci
    ALWEBER J'ai essayé ton code
    mais
    -si on test if Not Assigned(form2) resultat est false
    -Lorsque j'ai déplace le MDIChild (form2) à droite et à gauche, elle est lent (j'ai utilise RAD Studio 10.2.3)

  5. #5
    Membre actif
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2013
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Albanie

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2013
    Messages : 75
    Par défaut
    merci anapurna
    Tform(MDIChildren[i]).close;
    mais les MDIChild toujours restent ouvertes

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 108
    Par défaut
    attention form3 et form2 sont des références sur les fenêtres
    Libérer via MDIChildren[i] va produire des références invalides dans form2 et form3

    Citation Envoyé par unja2010
    Mais quand j'appuie à nouveau sur le bouton2 ou bouton3 le message(la form2 est active) est afficher donc les MDIChild sont restés "Assigned"
    Quelle est la solution pour les MDIChild ne restez pas "Assigned" Quand ils sont fermés ???
    unja2010 avait très bien compris que le problème venait du Assigned sur Form2 et Form3 qui ne prenait pas en compte la libération par MDIChildren[i]


    Vous savez qu'il existe la TList ou TObjectList depuis 20 ans ou même la TObjectList<TForm> depuis plus de 5 ans,
    Par pitié n'utilisé par des TStringList pour stocker des pointeurs sous forme de chaine, c'est immonde alors qu'il existe Objects[] qui permettrait de faire un tableau associatif d'une grande simplicité pour gérer une sorte de Factory\Multiton

    FormsByClass peut être au choix un membre privé de TForm1
    ou isolé dans une unité soit via un code procédural bâclé que j'ai fourni,
    l'idéal étant de faire une belle classe TMDIFormManager avec un singleton ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    var
      FormsByClass: TStringList = nil;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    finalization
      FreeAndNil(FormsByClass);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    function FindInstance(AFormClass: TFormClass): TForm;
    var
      idx: Integer;
    begin
      if not Assigned(FormsByClass) then
      begin
        FormsByClass := TStringList.Create();
        FormsByClass.Duplicates := dupError;
        FormsByClass.Sorted := True;
      end;
     
      idx := FormsByClass.IndexOf(AFormClass.ClassName());
      if idx < 0 then
        idx := FormsByClass.AddObject(AFormClass.ClassName(), AFormClass.Create(Application));
     
      Result := FormsByClass.Objects[idx] as TForm;
    end;
     
    procedure UnregisterInstance(AFormClass: TFormClass);
    var
      idx: Integer;
    begin
      if Assigned(FormsByClass) then
      begin
        idx := FormsByClass.IndexOf(AFormClass.ClassName());
        if idx >= 0 then
         FormsByClass.Delete(idx);
      end;
    end;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure Tform1.Button2Click(Sender: TObject);
    begin
       FindInstance(TForm2).Show();
    end;
     
    procedure Tform1.Button3Click(Sender: TObject);
    begin
       FindInstance(TForm3).Show();
    end;
    Important pour que les instances libérées soit purgées de la table d'association
    C'est ça qui te manquait pour libérer Form2 et Form3
    Je te recommande vivement de supprimer les variables globales Form2 et Form3
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    procedure TForm2.FormDestroy(Sender: TObject);
    begin
      UnregisterInstance(TForm2);
      // Dans ton cas c'était juste "Form2 := nil";
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TForm3.FormDestroy(Sender: TObject);
    begin
      UnregisterInstance(TForm3);
      // Dans ton cas c'était juste "Form3 := nil";
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre actif
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2013
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Albanie

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2013
    Messages : 75
    Par défaut
    merci

  8. #8
    Membre Expert
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 544
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 70
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 544
    Billets dans le blog
    10
    Par défaut
    Citation Envoyé par unja2010 Voir le message
    merci
    ALWEBER J'ai essayé ton code
    mais
    -si on test if Not Assigned(form2) resultat est false
    -Lorsque j'ai déplace le MDIChild (form2) à droite et à gauche, elle est lent (j'ai utilise RAD Studio 10.2.3)
    Information importante dans le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Application.CreateForm(TForm2, Form2);
      SlListeFiches.Add(intToStr(integer(pointer(form2)))) ;
    end;
    A chaque appel du createForm Form2 change d'adresse . C'est pour cela que l'on stocke cette adresse dans SlListeFiches.
    J'utilise plutôt le TStringList que le TList pour montrer aux stagiaires (Je donne beaucoup de cours sur Delphi) cette notion d'adresse mémoire.
    Ce mécanisme n'a aucun impact sur la lenteur que tu signales plutôt lié à la répétition de la gestion d'un événement.
    Pour des raisons de compatibilité ascendante (androïd et autres)on utilise plutôt d'autre mécanismes que mdi en voici un exemple en pièce jointe
    Nom : nouveau-1.png
Affichages : 322
Taille : 25,2 Ko
    Fichiers attachés Fichiers attachés

  9. #9
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 493
    Par défaut
    salut

    j'ai compris tu as oublié un truc tres important dans le formClose

    procedure Tform2.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    Action := caFree;
    inherited;//ici tu libere l'instance de ta forme
    end;

  10. #10
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 108
    Par défaut
    Confusion entre le gestionnaire d'évènement OnClose et la redéfinition d'une méthode virtuelle tel que Destroy
    le inherited dans ce cas est éliminé à la compilation
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 07/03/2006, 15h54
  2. tester si mon programme a liberer toute la memoire
    Par Mokhtar BEN MESSAOUD dans le forum C
    Réponses: 2
    Dernier message: 14/11/2005, 16h55
  3. [JVM]Libérer de la mémoire
    Par Vrylx dans le forum Général Java
    Réponses: 8
    Dernier message: 13/10/2005, 16h58
  4. comment demander a un serveur sql de liberer de la memoire
    Par timsah dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 07/09/2005, 11h24
  5. [FORMS] Utilisation de DLL avec ORA_FFI
    Par Nounoursonne dans le forum Forms
    Réponses: 2
    Dernier message: 07/12/2004, 09h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo