Remplir tableau avec le contenu d'un CheckBoxList [Résolu]

Signaler
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
-
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
-
Bonsoir :)
Après beaucoup de recherche je n'ai pas réussi à trouver un exemple assez simple pour ce que je cherche à faire....

Je cherche simplement à remplir une colonne d'un tableau multidimensionnel par les ItemsIndex d'un CheckListBox et l'autre colonne par les Items de ce même CheckListBox. Le tout dans une fonction récursive.
Le script semble « correct » (il passe au compilateur) mais lors de l'exécution du script ça plante le prog.

Message d'erreur >> Violation d'accès à l'adresse 00404238 dans le module 'blabla.exe'. Ecriture de l'adresse 00000072.

var
  Form1: TForm1;
  c: Integer;
  b: Integer;
  Result : Integer;
  ResultTotal : Integer;
  StopProcess : Boolean;
  MonTableau: array of array of String;


function ListFiles(Chemin:String):Integer;
var
S : TSearchRec;

begin
 Chemin:=IncludeTrailingPathDelimiter(Chemin);
 Form1.Label1.Caption:='Recherche dans '+Chemin;
 Form1.CheckListBox1.Refresh;

 If FindFirst(Chemin+'*.*',faAnyFile,S)=0
 then begin
  repeat
   Application.ProcessMessages;
   if (StopProcess) then exit else
   if (S.Name<>'.')And(s.Name<>'..')
   then begin
    if (S.Attr And faDirectory)<>0
    then
     begin
     Result:=Result+ListFiles(Chemin+S.FindData.cFileName);
     Inc(ResultTotal);
     end
    else
     if MatchesMask(S.Name, 'TTTT*.*') then
      begin
       Form1.CheckListBox1.Items.Add(S.Name);
       Inc(Result);
       SetLength(MonTableau,1,Result-1);
       For b:=0 To Length(Form1.CheckListBox1.Items[b]) do //    c'est ici que ça pose problème
       MonTableau[1,b]:=Form1.CheckListBox1.Items[b];      //    c'est ici que ça pose problème
      end;
  end;
  Until FindNext(S) <> 0;
   FindClose(S);
  end;
end;



L'aide de Delphi m'a plus embrouillé qu'autre chose -_-
Merci de votre aide !

18 réponses

Messages postés
263
Date d'inscription
lundi 27 octobre 2003
Statut
Membre
Dernière intervention
28 avril 2021
13
Salut,
ThWilliam a raison pourquoi un tableau 2D pour cette fonction .
Enfin ...
var
    Form1: TForm1;
    ResultFichier : Integer;
    ResultDossier : Integer;
    StopProcess   : Boolean;
    MonTableau    : array of array of String;

function ListFiles(Chemin, FindF:String; List:TStrings):Integer;
Var
    S : TSearchRec;
begin
    Chemin:=IncludeTrailingPathDelimiter(Chemin);
    Result:=0;
    If FindFirst(Chemin+'*.*',faAnyFile,S)=0 then
    begin
        repeat
            Application.ProcessMessages;
            if (StopProcess) then
                Exit
            else
            begin
                if (S.Name<>'.')And(s.Name<>'..')then
                begin
                    if (S.Attr And faDirectory)<>0 then
                    begin
                        ListFiles(Chemin+S.FindData.cFileName,FindF,List);
                        Inc(ResultDossier);
                    end
                    else
                    begin
                        if MatchesMask(S.Name, FindF) then
                        begin
                            Inc(ResultFichier);
                            List.Add(S.Name+' (Index '+IntTostr(ResultFichier-1)+')');
                            SetLength(MonTableau[0],ResultFichier);
                            SetLength(MonTableau[1],ResultFichier);
                            MonTableau[0,ResultFichier-1]:='Index '+IntTostr(ResultFichier-1);
                            MonTableau[1,ResultFichier-1]:=Chemin+S.Name;
                        end;
                    end;
                end;
            end;
        Until FindNext(S) <> 0;
        FindClose(S);
    end;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
    ResultFichier:=0;
    ResultDossier:=0;
    CheckListBox1.Clear;
    SetLength(MonTableau,2);
    Label1.Caption:='Recherche dans C:\Test';
    ListFiles('C:\Test','TTTT*.*',CheckListBox1.Items);
    Label2.Caption:=Format('Resultats : %d Dossiers et %d Fichiers',[ResultDossier,ResultFichier]);
end;

Dans le tableau : Index 0 | C:\Test\TTTTtest.jpg ...
Dans le CheckListBox : TTTTTest.jpg (Index 0) ...
Voilà courage
@+yanb
Messages postés
418
Date d'inscription
mardi 3 janvier 2006
Statut
Membre
Dernière intervention
26 novembre 2013
3
Re-bonjour.

"je n'ai pas réussi à déclarer lbOwnerDrawFixed" : tu as, je suppose, créer ton CheckListBox en mode designtime. Dans l'inspecteur d'objets, il suffit de modifier la propriété "Style". Puis dans les événements, double clic sur "OnDrawItem".

"Je souhaite supprimer certains des fichiers affichés, cette méthode le permet-elle ?"
Oui, sans aucun problème, puisque tes items du checkboxlist = chemin complet + nom de fichier.
Mais 2 remarques :
1) comme tu n'affiches pas le chemin, il est possible d'avoir à l'affichage deux ou plusieurs fichiers portant le même nom (pcq se trouvant dans des dossiers différents). Donc attention à choisir le bon !
2) remarque valable pour tout delete de plusieurs items dans une liste : toujours commencer par la fin de la liste :
for I:= CheckListBox1.Count - 1 downto 0 do...
en effet, à chaque delete d'un item, l'item suivant prend la place et l'indice de l'item effacé (et ainsi de suite...) + la propriété Count est réactualisée.

A +
Thierry
Messages postés
263
Date d'inscription
lundi 27 octobre 2003
Statut
Membre
Dernière intervention
28 avril 2021
13
Salut,
On a tout donné, où est la difficulté dans le code de ThWilliam.
Allez un effort pour la suppression.
var
  Form1: TForm1;
  StopProcess : Boolean;

function ListFiles(Chemin, FindF:String; List:TStrings):Integer;
var
    S : TSearchRec;
begin
    Chemin:=IncludeTrailingPathDelimiter(Chemin);
    Result:=0;
    If FindFirst(Chemin+'*.*',faAnyFile,S)=0 then
        repeat
            Application.ProcessMessages;
            if (StopProcess) then
                Exit
            else
                if (S.Name<>'.')And(s.Name<>'..')then
                    if (S.Attr And faDirectory)<>0 then
                        ListFiles(Chemin+S.FindData.cFileName,FindF,List)
                    else
                        if MatchesMask(S.Name, FindF) then
                            List.Add(Chemin+S.Name);
        Until FindNext(S) <> 0;
        FindClose(S);
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
    CheckListBox1.Style:=lbOwnerDrawFixed;
    CheckListBox1.Clear;
    Label1.Caption:='Recherche dans '+Direct;
    ListFiles('C:\Test','TTTT*.*',CheckListBox1.Items);
end;

procedure TForm1.CheckListBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
begin
    with CheckListBox1 do
        Canvas.TextRect(Rect,Rect.Left, Rect.Top,ExtractFileName(Items[Index]));
end;

@+ yanb
Messages postés
418
Date d'inscription
mardi 3 janvier 2006
Statut
Membre
Dernière intervention
26 novembre 2013
3
with CheckListBox1 do
Canvas.TextRect(Rect, Rect.Left
, Rect.Top, ExtractFileName(Items[Index]));
Messages postés
675
Date d'inscription
jeudi 17 avril 2008
Statut
Membre
Dernière intervention
19 février 2019
13
bonjour
For b:=0 To Length(Form1.CheckListBox1.Items[b])
je pense qu'il faut mettre " - 1 " car la longueur de la chaine est calculée de 1 à length, alors que le tableau est indicé à partir de 0
cordialement
Dubois77
Messages postés
263
Date d'inscription
lundi 27 octobre 2003
Statut
Membre
Dernière intervention
28 avril 2021
13
Salut,
Le dimensionnement tableau
Result à utiliser pour les fonctions pas en variable
etc ...
var
  Form1: TForm1;
  c: Integer;
  b: Integer;
  //Result : Integer;
  ResultTotal : Integer;
  StopProcess : Boolean;
  MonTableau: array of array of String;


function ListFiles(Chemin:String):Integer;
var
S : TSearchRec;

begin
 Chemin:=IncludeTrailingPathDelimiter(Chemin);
 Form1.Label1.Caption:='Recherche dans '+Chemin;
 Form1.CheckListBox1.Refresh;
 Result:=0;
 SetLength(MonTableau,2);
 If FindFirst(Chemin+'*.*',faAnyFile,S)=0
 then begin
  repeat
   Application.ProcessMessages;
   if (StopProcess) then exit else
   if (S.Name<>'.')And(s.Name<>'..')
   then begin
    if (S.Attr And faDirectory)<>0
    then
     begin
     Result:=Result+ListFiles(Chemin+S.FindData.cFileName);
     Inc(ResultTotal);
     end
    else
     if MatchesMask(S.Name, 'TTTT*.*') then
      begin
       Form1.CheckListBox1.Items.Add(S.Name);
       Inc(Result);       
       SetLength(MonTableau[0],Result);
       SetLength(MonTableau[1],Result);
       For b:=0 To Form1.CheckListBox1.Items.Count-1 do //    c'est ici que ça pose problème
       begin
         MonTableau[0,b]:=IntToStr(b+1);
         MonTableau[1,b]:=Form1.CheckListBox1.Items[b];      //    c'est ici que ça pose problème
       end;
      end;
  end;
  Until FindNext(S) <> 0;
   FindClose(S);
  end;
end;

Normalement ca devrait régler le pb
@+yanb
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
2
Et si je met autre chose à la place de Result ?
Une variable "blabla" ça marchera aussi ?

Merci de vos réponses, j'essaie ce soir.
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
2
J'ai essayé vos 2 méthodes : même erreur
Je ne sais pas d'où ça vient....
Messages postés
251
Date d'inscription
dimanche 7 décembre 2003
Statut
Membre
Dernière intervention
11 novembre 2016

Bonjour

Questions
1 pourquoi avoir un tableau a 2 dimension si c'est pour uniquement remplir la 2
MonTableau[1,b]:=Form1.CheckListBox1.Items[b]
2 a quoi sert cette boucle For b:=0 To Length(Form1.CheckListBox1.Items[b]) do
il serait mieux de faire
Form1.CheckListBox1.Items.Add(S.Name);
Inc(Result);
SetLength(MonTableau[1],Result);
MonTableau[1,Result -1]:=Form1.CheckListBox1.Items[Result -1]

A+
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
2
Et bien en fait je comptais remplir la première colonne après :s (mon script est incomplet, c'est vrai).
Et la boucle c'est parce que je n'ai pas réussi à pondre quelque chose de plus "cohérent"....

Merci pour ton aide fbalien mais ça ne marche pas...
En gros, je cherche à remplir comme ceci :

tableau :
[0|dossier/TTTT01.jpg]
[1|TTTThdfhdd.mpg]
[2|dossier/blabla/TTTTblabla.rtf]
[3|dossier/bla/TTTTjjjjjjjjj.jpg]
[4|..........]

checklistbox :
[]TTTT01.jpg (index:0)
[]TTTThdfhdd.jmpg (index:1)
[]TTTTblabla.rtf (index:2)
[]TTTTjjjjjjjjj.jpg (index:3)
[]TTTT............ (index:4)




J'ai essayé ceci :
Form1.CheckListBox1.Items.Add(S.Name);
Inc(Result);
SetLength(MonTableau[1],Result-1);
MonTableau[0,Result -1]:=IntToStr(Result-1);
MonTableau[1,Result -1]:=Chemin+S.Name;

sans succès :/

Merci de votre aide !
Messages postés
263
Date d'inscription
lundi 27 octobre 2003
Statut
Membre
Dernière intervention
28 avril 2021
13
Salut,
surprenant que le message soit toujours présent...
je vais le tester, mais le pb vient bien du dimensionnement du tableau,
tu essaye de mettre des valeur dans un tableau ou les tailles ne sont pas ou mal fixés.
@+yanb
Messages postés
418
Date d'inscription
mardi 3 janvier 2006
Statut
Membre
Dernière intervention
26 novembre 2013
3
Salut,

Si je comprends bien, tu utilises un tableau 2D pour stocker :
- index du fichier trouvé
- chemin + nom fichier

A quoi te sert ce tableau !?
- comme tu ajoutes à chaque fichier trouvé son nom dans un checklistbox, l'index du fichier = index de l'item du checklistbox.
- tu utilises la 2° dimension pour stocker le chemin complet. Mais tu peux très bien assigner à l'item du checklistbox le chemin + le nom. Si tu ne veux voir affiché que le nom, tu "dessines" toi-même le texte à afficher.

Propriété Style du checklistbox = lbOwnerDrawFixed

puis événement OnDrawItem, avec un code du genre :

procedure TForm1.CheckListBox1DrawItem(Control: TWinControl;
Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin
with CheckListBox1 do
Canvas.TextRect(Rect,Rect.Left, Rect.Top,ExtractFileName(Items[Index]));
end;

A +
Thierry
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
2
@ ThWilliam > je ne pensais pas que l'on pouvait faire une telle chose !!
C'est un ami qui m'a conseillé de passer par un tableau, je suis issu des BDD, ça m'a paru être une bonne idée.
Cette idée m'intéresse beaucoup !
Peux-tu m'en dire plus, je n'ai pas réussi à déclarer lbOwnerDrawFixed.

Je souhaite supprimer certains des fichiers affichés, cette méthode le permet-elle ?



@ yanb > merci mais je vais me concentrer sur la méthode de ThWilliam.
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
2
Et après plusieurs essais je n'ai pas réussi à faire fonctionner
Canvas.TextRect(Rect,Rect.Left, Rect.Top,ExtractFileName(Items[Index]));

Je suis vraiment nul --'
j'ai déclaré Form1.CheckListBox1.Style:=lbOwnerDrawFixed; avant la fonction récursive....
Messages postés
263
Date d'inscription
lundi 27 octobre 2003
Statut
Membre
Dernière intervention
28 avril 2021
13
oups erreur il faut supprimer la ligne :
Label1.Caption:='Recherche dans '+Direct;
ou la remplacer par Label1.Caption:='Recherche dans C:\Test';
@+yanb
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
2
[b]with CheckListBox1 do
Canvas.TextRect(Rect,Rect.right, Rect.Top,ExtractFileName(Items[Index]));/b
n'a aucun effet je me retrouve avec les chemins+noms de fichiers dans le CHL.

Merci pour le script pour la suppression !
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
2
Encore mieux... le OnDrawItem vide les items, j'ai toutes les cases à cocher mais plus le contenu (nom de fichier ou chemin).... je suis perdu.
Messages postés
233
Date d'inscription
jeudi 30 septembre 2004
Statut
Membre
Dernière intervention
26 juin 2011
2
Parfait !!!
Comme prévu CheckListBox1.Items[i] affiche le chemin + nom du fichier !

Je vous aime les gars