Remplir tableau avec le contenu d'un CheckBoxList

Résolu
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 - 4 juin 2010 à 00:00
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 - 6 juin 2010 à 13:27
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

cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
5 juin 2010 à 12:42
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
3
ThWilliam Messages postés 418 Date d'inscription mardi 3 janvier 2006 Statut Membre Dernière intervention 26 novembre 2013 4
5 juin 2010 à 14:57
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
3
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
5 juin 2010 à 15:34
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
3
ThWilliam Messages postés 418 Date d'inscription mardi 3 janvier 2006 Statut Membre Dernière intervention 26 novembre 2013 4
5 juin 2010 à 19:13
with CheckListBox1 do
Canvas.TextRect(Rect, Rect.Left
, Rect.Top, ExtractFileName(Items[Index]));
3

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
dubois77 Messages postés 675 Date d'inscription jeudi 17 avril 2008 Statut Membre Dernière intervention 19 février 2019 14
4 juin 2010 à 07:33
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
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
4 juin 2010 à 10:59
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
0
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 5
4 juin 2010 à 13:31
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.
0
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 5
4 juin 2010 à 19:46
J'ai essayé vos 2 méthodes : même erreur
Je ne sais pas d'où ça vient....
0
fbalien Messages postés 251 Date d'inscription dimanche 7 décembre 2003 Statut Membre Dernière intervention 11 novembre 2016
4 juin 2010 à 23:44
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+
0
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 5
5 juin 2010 à 02:07
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 !
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
5 juin 2010 à 10:24
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
0
ThWilliam Messages postés 418 Date d'inscription mardi 3 janvier 2006 Statut Membre Dernière intervention 26 novembre 2013 4
5 juin 2010 à 11:56
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
0
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 5
5 juin 2010 à 14:23
@ 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.
0
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 5
5 juin 2010 à 14:58
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....
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
5 juin 2010 à 15:48
oups erreur il faut supprimer la ligne :
Label1.Caption:='Recherche dans '+Direct;
ou la remplacer par Label1.Caption:='Recherche dans C:\Test';
@+yanb
0
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 5
5 juin 2010 à 17:47
[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 !
0
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 5
5 juin 2010 à 18:00
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.
0
cs_JackNUMBER Messages postés 233 Date d'inscription jeudi 30 septembre 2004 Statut Membre Dernière intervention 26 juin 2011 5
6 juin 2010 à 13:27
Parfait !!!
Comme prévu CheckListBox1.Items[i] affiche le chemin + nom du fichier !

Je vous aime les gars
0
Rejoignez-nous