MAKE CAB + CHECKLISTBOX

f0xi
Messages postés
4205
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
12 mars 2022
- 20 avril 2006 à 18:33
cs_Forman
Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
- 29 juin 2006 à 19:53
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/37164-make-cab-checklistbox

cs_Forman
Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
1
29 juin 2006 à 19:53
Une autre solution pour ne pas avoir à se soucier de la libération de la mémoire est la suivante:

type
IStrings=interface
function GetCount:Integer;
property Count:Integer read GetCount;

function GetItem(const Index:Integer):string;
procedure SetItem(const Index:Integer;const Value:string);
property Item[Index:Integer]:string read GetItem write SetItem;
end;

TStringsImplementation=class(TInterfacedObject,IStrings)
function GetCount:Integer;
function GetItem(const Index:Integer):string;
procedure SetItem(const Index:Integer;const Value:string);
destructor Destroy;override;
end;

...faire l'implémentation de l'objet TStringsImplementation...

On pourrait alors déclarer la fonction qui renvoie une liste de chaînes de la fonction suivante:

function TCheckListBox.GetChecks:IStrings;
begin
Result:=TStringsImplementation.Create;
Result.Add(...);
end;

Lorsque quelqu'un utilise la fonction ainsi:

with CheckListBox1.GetChecks do begin
ShowMessage('Il y a '+IntToStr(Count)+' items sélecionnés');
end;

la mémoire sera libérée, car il y a des appels implicites à _AddRef et _Release qui font -avec le mécanisme de comptage de référence des interfaces- qu'à l'issue de cet appel, l'objet TStringsImplementation est détruit. C'est une solution propre et élégante, mais qui nécessite toutefois d'écrire un peu plus de code (ceci dit écrire l'implémentation de TStringsImplementation ne me paraît pas très difficile...).
cs_Forman
Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
1
29 juin 2006 à 19:44
procedure AddToList(List : TStrings);
begin
List.BeginUpdate;
try
List.Add(...);
finally
List.EndUpdate;
end;
end;

"AddToList" a l'avantage d'être un nom explicite. BeginUpdate...EndUpdate permet de ne pas dégrader les performances avec des TStrings associés à des contrôles par exemple.
f0xi
Messages postés
4205
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
12 mars 2022
38
23 avril 2006 à 22:04
heu il me semble que tu parle de cette phrase : "Avantage du point que souleve Nono, c'est que si on ecrit tout de meme une fonction, elle permet de liberer la valeur du resultat pour passer un retour de control booléen ou tout autre retour."

en fait je parler de rendre disponible le retour de la fonction pour l'utiliser comme control ou comme information.

pour ce que tu dis :

La création est inutile ici.
procedure SetList(List : TStrings);
begin
list.Clear
List.Add(...);
end;


attention, toute fois, si il s'agit d'une liste non visuelle, pas de probleme, par contre si il s'agit d'un composant visuel, le fait de faire des ADD vas rafraichir le compo et degradé les preformance d'ou le buffer de type TStringList pour d'abord créer la liste puis envoyer la liste a l'objet en argument.
cs_Nono40
Messages postés
962
Date d'inscription
mercredi 3 avril 2002
Statut
Membre
Dernière intervention
12 septembre 2006
2
21 avril 2006 à 22:10
Merci je sais la différence entre un Whiol et un repeat....

Regarde ma solution de près et tu veras que le code Repeat Until n'est appelé que si le If est vrai. Le traitement ne seront donc bien effectué que sur le premier élément.

Pour ta solution
procedure SetList(List : TStrings);
var TMPLIST : TStringList;
begin
try
TMPLIST := TStringList.Create;
...
TMPLIST.Add(...);
...
List.Assign(TMPLIST);
finally
TMPLIST.Free;
end;
end;

La création est inutile ici.
procedure SetList(List : TStrings);
begin
list.Clear
List.Add(...);
end;

Pour répondre à un point au dessus aussi, tu dis que le résultat est libéré car c'est une variable locale. C'est FAUX. Seules les chaines et les tableaux dynamiques sont dans ce cas, dans tous les autres c'est à toi de le gérer.
f0xi
Messages postés
4205
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
12 mars 2022
38
21 avril 2006 à 11:02
>>> J'ai pas compris où est mon erreur sur le getselection ?

Erreur que j'ai répétée et que nono a corrigée, c'est qu'un retour de ce type ne serat jamais libéré durant l'execution, soit, pas liberée en memoire.

donc si la liste pese 15Koctet et qu'on appel 100 fois la fonction, on provoque une fuite de memoire de 1500 Ko (1.5Mo)

donc il faut faire comme on vient de te le dire, passer la List dans les arguments et non dans le retour de fonction.

soit :

procedure TCheckListBox.GetSelection(OutList : TStrings);
var
i : Integer;
TPL : TStringList;
begin
try
TPL : TStringList;
For i := 0 to Items.Count - 1 do
if Checked[i] then TPL.Add(Items.Strings[i]);
OutList.Assign(TPL);
finally
TPL.free;
end;
end;



>> J'ai mis le sender sur le CheckAll pour pouvoir l'appeler directement avec le click sur le menuitem "Tout cocher" mais peut etre qu'il y a un autre moyen ?

pas besoin, Tu crée la methode "TouCocher1Click" et tu place le code CheckList.CheckAll;
dedans.
ce serat plus propre car comme je te l'ai dis, ce sont des methodes et non des evenements. nuance.
en plus, cela permet de ne pas passer un argument inutile aux methodes ...
car un il ne faut pas oublier qu'un argument inutile prend de la place pour rien en memoire.

donc tu auras :

procedure TForm1.ToutCocher1Click(Sender : TObject);
begin
CheckList.CheckAll;
end;

et non dans l'inspecteur d'objet :
OnClick >> CheckList.CheckAll
Afficher les 9 commentaires