Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TreeView und ListView (https://www.delphipraxis.net/99376-treeview-und-listview.html)

Malte Koch 11. Sep 2007 11:48


TreeView und ListView
 
Hallo zusammen,

Ich arbeite noch nicht sehr lange mit Delphi und habe nun folgendes Problem

Ich lasse mir in einem TreeView die Ordner aus einem ausgewählten Laufwerk anzeigen und möchte jetzt in einer ListView die Dateien anzeigen lassen die sich in den Ordnern befinden. Es sollen jedoch nur die Dateien angezeigt werden die auch in dem markierten Ordner sind.

Bitte um schnelle Hilfe

MFG Malte

Matze 11. Sep 2007 11:52

Re: TreeView und ListView
 
Hallo, herzlich Willkommen!

Mit FindAllFilesFindAllFiles kannst du alle Dateien eines Verzeichnisses ermitteln. Früher gab es in Delphi TShellTreeView und TShellListView. Ob diese noch vorhanden sind, weiß ich nicht, doch diese Komponenten sind genau dafür da und nehmen dir die Arbeit ab.

s-off 11. Sep 2007 11:55

Re: TreeView und ListView
 
Hallo,

ich weiss nicht, welche Version von Delphi Du verwendest, aber in Delphi 7 gab es noch die Komponenten 'ShellTreeView' und 'ShellListView'. Zu finden waren sie m.M. nach unter der Rubrik 'Beispiele'.

Seit BDS2006 (oder früher?!) müssen diese manuell nachinstalliert werden. Die Packages liegen unter (bspw.) C:\Programme\Borland\BDS\4.0\Demos\DelphiWin32\VCL Win32\ShellControls

Edit: Wieder zu langsam

Malte Koch 11. Sep 2007 12:01

Re: TreeView und ListView
 
Ich benutze CodeGear RAD Studio 2007 Professionell

Ich weis nicht so genau wie ich die FindAllFiles funktion einbinden soll. Wenn ihr mir da helfen könntet?

s-off 11. Sep 2007 12:04

Re: TreeView und ListView
 
Installiere Dir die ShellControls. Wo diese liegen, habe ich bereits erwähnt. Dann benötigst Du FindAllFIles nicht.

Ansonsten:
Zu 'FindAllFiles' findest Du eine Demo von Luckie, wenn Du auf den von Matze geposteten Link klickst.

Malte Koch 11. Sep 2007 13:06

Re: TreeView und ListView
 
Danke für die Antworten aber das ist alles nicht so wie ich mir das vorstelle. Vielleicht muss ich mich nochmal anders ausdrücken.

1. Ich habe eine Prozedur die für jedes Laufwerk des Rechners einen Button erzeugt.
2. Beim Click auf einen der Button werden die Ordner ausgelesen, die auf diesem Laufwerk vorhanden sind, und in einem TreeView dargestellt.
3. Wenn ich jetzt im TreeView einen Ordner anklicke(markiere) soll er mir in einem ListView (rechts neben dem TreeView) die einzelnen Dateien, die in dem ausgewählten Ordner sind) anzeigen.


Die ShellControls habe ich nicht bei meinem Delphi.

SMALLID 11. Sep 2007 13:17

Re: TreeView und ListView
 
Da gibts doch vorgefertigte Componenten, die mit Delphi mitgeliefert werden, die das alles per Click/Properties erledigen. (Bei Interesse nochmal nachfragen, dann schau ich mal). Wenn du es aus irgendeinem Grund aber per Hand machen MUSST, dann geht das auf jeden Fall mit dem auslesen der Files und dem Platzieren in einem Listview. Willst du denn alle unterordner in dem Listview mit anzeigen oder nur (ausschließlich) solche Items, die auch Dateien sind (=keine Ordner)?

Malte Koch 11. Sep 2007 13:21

Re: TreeView und ListView
 
Die vorgefertigten Komponenten gefallen mir nicht. Beim TreeView gibt es kein "+" und "-" vor den Knoten.

Im List View sollen hinterher NUR Dateien stehen. aber halt auch nur die zum angewählten Ordner. Ich hatte es schon soweit das er mir alle anzeigt, was natürlich nicht Sinn der Sache ist.

SMALLID 11. Sep 2007 13:24

Re: TreeView und ListView
 
was bedeutet denn "alle" dateien? Ich kann mir gar nicht vorstellen, dass es anders geht, als nur die im ordner enthaltenen dateien anzuzeigen. Moment ich bastel ma rum ...

Andreas L. 11. Sep 2007 13:24

Re: TreeView und ListView
 
Die ShellControls findest du hier:
...\Borland\BDS\4.0\Demos\DelphiWin32\VCLWin32\She llControls

Einfach beide Packages compilieren und dann installieren. Du bekommst dann in der Komponentenpalette eine neue Kategorie "Samples".

Das + und - beim Knoten kannst du mit einer Eigenschaft, dir mir gerade nicht einfällt, an bzw. ausschalten.

SMALLID 11. Sep 2007 13:33

Re: TreeView und ListView
 
Wie Andreas schon sagt ist der eleganteste Weg einfach das Design (+/-, etc.) der schon vorhandenen Komponenten zu ändern.

Wenn es mit ShellCtrl nicht klappt kannst du mit FindFirst, FindNext, etc. arbeiten. Dort kannst du nämlich auch gleich angeben, ob du Ordner includen willst oder nicht.

Bsp.-Quellcode zum Selbststudium:

Delphi-Quellcode:
var
  SearchRec: TSearchRec;
procedure TForm1.SearchClick(Sender: TObject);
begin
  FindFirst('c:\Program Files\MyProgram\bin\

*.*', faAnyFile, SearchRec);
  Label1.Caption := SearchRec.Name + ' is ' + IntToStr(SearchRec.Size) + " bytes in size';
end;
procedure TForm1.AgainClick(Sender: TObject);
begin
  if FindNext(SearchRec) = 0 then
    Label1.Caption := SearchRec.Name + ' is ' + IntToStr(SearchRec.Size) + ' bytes in size'
  else
    FindClose(SearchRec);
end;
Wenn du in der Hilfe mal nach "Dateien" suchst und den Filter auf DevStudio für Win32 setzt, danna auf "Methoden zur Ein-/Ausgabe" klickst und noch ein bissl rumsuchst, findest du eine ganze Anleitung dazu.

Ansonsten wie gesagt die schon vorhandenen Komponenten anpassen. Und bei Fragen nochmal posten :)

Malte Koch 11. Sep 2007 13:43

Re: TreeView und ListView
 
Hier ist die Prozedur die die Verzeichnisse ausliest. Jetzt ist die Frage, ob ich hier auch die Dateien schon suche oder ob ich dafür ne eigene Prozedur schreibe, die nur beim Klick auf den ausgegebenen Ordner ausgeführt wird.

Delphi-Quellcode:
procedure TForm2.HoleVerzeichnisse(const Pfad: String; var Tree: TTreeView;var ListView: TListView; Start: TTreeNode);
var
 SR: TSearchRec;

  begin
    if FindFirst(Pfad + '\*.*', faAnyFile, SR) = 0 then
  repeat
    Application.ProcessMessages;
    if (SR.Attr AND faDirectory = faDirectory) AND (SR.Name[1] <> '.')
        AND (SR.Name[1] <> '_') then
    begin
        baum := Tree.Items.Addchild(Start, SR.Name);
        baum.ImageIndex := 1;
        baum.StateIndex := 2;
        HoleVerzeichnisse(Pfad + '\' + SR.Name, Tree, ListView, Baum);
      end;
  until (FindNext(SR) <> 0);
  SysUtils.FindClose(SR);
  end;

SMALLID 11. Sep 2007 14:11

Re: TreeView und ListView
 
Du machst beim OnClik des treeviews eine Art "HoleDateien" mit den gleichen Parametern. Die schreibt dann die Elemente von "Pfad" (also dem aus dem Item und den Überitems zusammengesetzten String des TreeViews) wo (SR.Attr AND NOT faDirectory = faAnyFile) und schreibt die in den ListView.

Malte Koch 11. Sep 2007 14:30

Re: TreeView und ListView
 
1. Muss ich OnClick oder OnChange nehmen?

2. Wie komm ich in der Funktion an den Pfad dran? Also wie kann ich auslesen was ich angeklickt habe?

Malte Koch 11. Sep 2007 15:05

Re: TreeView und ListView
 
So sieht meine Prozedur bis jetzt aus. Jedoch weis ich nicht genau wie ich denn jetzt den Namen in das Item packe.

Ihr wisst was ich meine??

Delphi-Quellcode:
procedure TForm2.HoleDateien(const Pfad: String);
var
 SR: TSearchRec;
  begin
    if FindFirst(Pfad + '\*.*', faAnyFile, SR) = 0 then
  repeat
    Application.ProcessMessages;
    if (SR.Attr OR faAnyfile = faAnyFile) AND (SR.Name[1] <> '.')
        AND (SR.Name[1] <> '_') then
    begin
         ListView1.Items.Add ;
         ListItem.Caption := (SR.Name);

        baum.ImageIndex := 1;
        baum.StateIndex := 2;
        HoleDateien(Pfad);
      end;
  until (FindNext(SR) <> 0);
  SysUtils.FindClose(SR);
  end;

Mackhack 11. Sep 2007 15:32

Re: TreeView und ListView
 
Hier hab ich dir mal ein uraltes Beispiel das dir auch deine +/- Anzeigt vor den Eintraegen im Treeview!

Delphi-Quellcode:
procedure Verzeichnisse_Einlesen(Tree : TTreeView; Verzeichnis : String; Eintrag : TTreeNode; Mit_Dateien : Boolean);
Var
  SearchRec  : TSearchRec;
  EintragTemp : TTreeNode;
  List       : TStringList;
  Buf        : String;
  I          : Integer;
Begin
  Tree.Items.BeginUpdate;
  List:= TStringList.Create;
  If Verzeichnis[Length(Verzeichnis)] <> '\' Then
  Begin
    Verzeichnis:= Verzeichnis + '\';
  End;
  If FindFirst(Verzeichnis + '*.*', faDirectory, SearchRec) = 0 Then
  Begin
    Repeat
      If (SearchRec.Attr And faDirectory = faDirectory) And (SearchRec.Name[1] <> '.') Then
      Begin
        //Eintrag ist ein Verzeichnis
        If (SearchRec.Attr And faDirectory > 0) Then
        Begin
          //zum aktuellen Eintrag hinzufügen
          Eintrag:= Tree.Items.AddChild(Eintrag, SearchRec.Name);
          EintragTemp:= Tree.Items.Add(Nil, Buf);
          EintragTemp.ImageIndex   := 0; //Ummarkiert
          EintragTemp.SelectedIndex := 0; //Markiert
          EintragTemp.StateIndex   := -1;
          //Eintrag merken
          EintragTemp:= Eintrag.Parent;
          //auf Untereinträge prüfen
          Verzeichnisse_Einlesen(Tree, Verzeichnis + SearchRec.Name, Eintrag, Mit_Dateien);
          //Eintrag wiederholen
          Eintrag:= EintragTemp;
        End
        Else
          //Eintrag ist eine Datei
          If Mit_Dateien Then
          Begin
            If (SearchRec.Name[1] <> '.') And (SearchRec.Name[1] <> '..') Then
            Begin
              Tree.Items.AddChild(Eintrag, SearchRec.Name);
              Eintrag:= Tree.Items.Add(Nil, SearchRec.Name);
              EintragTemp:= Tree.Items.Add(Nil, List.Strings[I]);
              EintragTemp.ImageIndex   := 2; //Ummarkiert
              EintragTemp.SelectedIndex := 2; //Markiert
              EintragTemp.StateIndex   := -1;
            End;
          End;
        End;
    Until FindNext(SearchRec) <> 0;
    FindClose(SearchRec);
  End;
  Tree.Items.EndUpdate;
End;

procedure TForm1.Button2Click(Sender: TObject);
begin
  TreeView1.Items.Clear;
  Verzeichnisse_Einlesen(TreeView1, Edit2.Text, Nil, False);
end;

Malte Koch 12. Sep 2007 07:43

Re: TreeView und ListView
 
Ich hab es ja jetzt auch schon so, dass er mir das + und - anzeigt. Ich habe halt nur nen problem, dass er mir die Dateien aus den Ordnern in einem ListView anzeigt.

Matze 12. Sep 2007 08:18

Re: TreeView und ListView
 
Ich mache das immer so:

Delphi-Quellcode:
var MyItem: TListItem;

MyItem := ListView.Items.Add;
MyItem.ImageIndex := EinIndex;
MyItem.Caption := 'Inhalt der 1. Spalte';
MyItem.SubItems.Add('Inhalt der 2. Spalte');
MyItem.SubItems.Add('Inhalt der 3. Spalte');

Malte Koch 12. Sep 2007 14:49

Re: TreeView und ListView
 
Ich habe das jetzt hinbekommen.

Leider kann ich im moment nur die Dateien anzeigen die sich hinter dem ersten knoten verbergen.

Was muss ich denn ändern, damit der komplette Pfad mitübergeben wird?

Mackhack 12. Sep 2007 15:24

Re: TreeView und ListView
 
Zitat:

Zitat von Malte Koch
Ich habe das jetzt hinbekommen.

Leider kann ich im moment nur die Dateien anzeigen die sich hinter dem ersten knoten verbergen.

Was muss ich denn ändern, damit der komplette Pfad mitübergeben wird?

Zeig doch ein wenig Code dann kann man dir auch sagen warum du nur die Daten des ersten Knoten angezeigt bekommst!

Malte Koch 12. Sep 2007 15:29

Re: TreeView und ListView
 
Liest die Ordner aus:

Delphi-Quellcode:
procedure TForm2.HoleVerzeichnisse(const Pfad: String; var Tree: TTreeView;
                                  Start: TTreeNode);
var
 SR: TSearchRec;
  begin
    if FindFirst(Pfad + '\*.*', faAnyFile, SR) = 0 then
  repeat
    Application.ProcessMessages;
    if (SR.Attr AND faDirectory = faDirectory) AND (SR.Name[1] <> '.')
        AND (SR.Name[1] <> '_') then
    begin
      baum := Tree.Items.Addchild(Start, SR.Name);
      baum.SelectedIndex := 1;
      baum.ImageIndex := 1;
      baum.StateIndex := -1;
      HoleVerzeichnisse(Pfad+'\'+ SR.Name, Tree, baum);
    end;
  until (FindNext(SR) <> 0);
 SysUtils.FindClose(SR);
end;
Zeigt die entsprechenden Dateien an:

Delphi-Quellcode:
procedure TForm2.HoleDateien(const Pfad: String; ListV: TListView; Filter: String);
var
 SR: TSearchRec;
 anItem:TListItem;
   begin
    if FindFirst(Pfad + '\' + Filter, faAnyFile, SR) = 0 then
  repeat
    Application.ProcessMessages;
    if (SR.Attr AND faDirectory <> 16) AND (SR.Name[1] <> '.')
        AND (SR.Name[1] <> '_') then
    begin
            anItem:=ListV.Items.Add;
            anItem.Caption:=SR.Name;

            anItem.SubItems.Add( IntToStr(GetFileSizeEx(Pfad+'\'+SR.Name)div 1024));
            anItem.SubItems.Add( GetFileTypename(Pfad+'\'+SR.Name));
            anItem.SubItems.Add( DateToStr(GetFileLastAccessTime(Pfad+'\'+SR.name)));
            anItem.SubItems.Add( DateToStr(GetCreationTimeOfFile(Pfad+'\'+SR.Name)));
      end;
  until (FindNext(SR) <> 0);
  SysUtils.FindClose(SR);
end;

Mackhack 12. Sep 2007 21:06

Re: TreeView und ListView
 
Hm,

du musst auch noch auf

Delphi-Quellcode:
(  SR.Name[1] <> '..')
ueberpruefen!

Und was soll das sein?

Delphi-Quellcode:
  (SR.Name[1] <> '_')
Du weist schon dass du das ganze einfacher in einer einzigen Funktion mit Rekursion schreiben kannst?

Malte Koch 12. Sep 2007 21:57

Re: TreeView und ListView
 
Das
Delphi-Quellcode:
(SR.Name[1] <> '_')
habe ich gemacht, weil der mir sonst auch _history Ordner anzeigt was ich aber nich haben möchte.

Und
Delphi-Quellcode:
(SR.Name[1] <> '..')
hab ich nicht gemacht da ich es ja schon mit einem Punkt habe. Wenn das erste Zeichen ungleich '.' ist schliesst es '..' ja logischerweise auch aus, da dies ja schon 2 Zeichen sind.

Wie kann ich das denn in einer Funktion machen? Ich habe Stunden lang rumprobiert und es nicht hinbekommen. Danach habe ich mich dann für 2 Funktionen entschieden. Für eine Lösung in einer Funktion wäre ich sehr dankbar. Vorallem das mit der Rekursion wäre interessant, da ich somit dann auch Dateien aus SubOrdnern auslesen könnte.

Matze 12. Sep 2007 22:08

Re: TreeView und ListView
 
Siehe dir doch den Link in meinen ersten Beitrag (Beitrag #2) an. Da sind rekursive Funktionen zu finden, die du wenn, dann nur leicht anpassen musst.

Mackhack 12. Sep 2007 22:13

Re: TreeView und ListView
 
Entweder hast du meinen Beitrag #16 total ignoriert oder ich sehe net wo das Problem liegt :?: Du musst einfach wenn es im Result um einen Ordner handelt in diesen Ordner reingehen und dort weitersuchen bis es keine weiteren Unterordner mehr gibt.

Hab dir hier mal ein kleines Beispiel was du mit etwas anpassen verwenden kannst (hab ich aus einem aktuellen Projekt rauskopiert) oder aber auch einfach umschreiben kannst um Delphi's TSearchRec zu nutzen!

Delphi-Quellcode:
procedure SearchFiles(aRoot: String; var Files : TStringList; Mask: String = '*.*'; Recursive : Boolean = False);
var
  wfd : TWin32FindData;
  hFile : THandle;
begin
  aRoot := IncludeTrailingPathDelimiter(aRoot);
  if Recursive then
  begin
    hFile := FindFirstFile(PChar(aRoot + Mask), wfd);
    if ( hFile <> INVALID_HANDLE_VALUE ) then
    try
      repeat
        if ( wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = FILE_ATTRIBUTE_DIRECTORY ) then
        begin
          if ( (String(wfd.cFileName) <> '.') and (String(wfd.cFileName) <> '..') ) then
          begin
            SearchFiles(aRoot + wfd.cFileName, Files, Mask, Recursive);  // hier wird die Rekursion angewandt
          end;
        end;
      until FindNextFile(hFile, wfd) = False;
    finally
      Windows.FindClose(hFile);
    end;
  end;
  hFile := FindFirstFile(PChar(aRoot + Mask), wfd);
  if ( hFile <> INVALID_HANDLE_VALUE ) then
  try
    repeat
      if (wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY <> FILE_ATTRIBUTE_DIRECTORY ) then
      begin
        Files.Add(wfd.cFileName);
      end;
    until FindNextFile(hFile, wfd) = False;
  finally
    Windows.FindClose(hFile);
  end;
end;

Malte Koch 12. Sep 2007 22:24

Re: TreeView und ListView
 
Tut mir ja leid das ich das alles noch nicht sofort verstehe aber ich arbeite noch nicht so lange mit delphi.

Ich werde das morgen dann mal ausprobieren und meinen Erfolg hier posten!

Christian Seehase 12. Sep 2007 22:32

Re: TreeView und ListView
 
Moin Malte,

Zitat:

Zitat von Malte Koch
Und
Delphi-Quellcode:
(SR.Name[1] <> '..')
hab ich nicht gemacht da ich es ja schon mit einem Punkt habe. Wenn das erste Zeichen ungleich '.' ist schliesst es '..' ja logischerweise auch aus, da dies ja schon 2 Zeichen sind.

Ich denke Mackhack wollte darauf hinweisen, dass Du explizit auf

Delphi-Quellcode:
(SR.Name <> '.') and (SR.Name <> '..')
prüfen musst.

Eine Prüfung auf SR.Name[1] <> '.' ist schlichtweg falsch, da ein Datei-/Ordername durchaus mit einem Punkt beginnen kann.
Nur weil man das im Explorer nicht so eingeben kann heisst noch lange nicht, dass es nicht geht, bzw. nicht erlaubt ist ;-)

(ich weiss, dass man das oft so sieht, aber dadurch wird es nicht richtiger ;-))

Mackhack 12. Sep 2007 22:59

Re: TreeView und ListView
 
Zitat:

Zitat von Malte Koch
Tut mir ja leid das ich das alles noch nicht sofort verstehe aber ich arbeite noch nicht so lange mit delphi.

Ich werde das morgen dann mal ausprobieren und meinen Erfolg hier posten!

Ich glaube kaum dass du dich hier entschuldigen musst. Kein Meister ist vom Himmel gefallen und jeder hat mal klein angefangen. Ich wollte das auch nicht als erhobenen Zeigefinger darstellen sondern nur drauf hinweisen dass du die Hilfen die du hier bekommst nicht uebersehen oder ignorieren sollst. Mehr net.

Und klar sag ruhig wenn es geklappt hat oder ob du noch mehr Hilfe brauchst, dazu ist ja das Forum da!

Malte Koch 13. Sep 2007 08:28

Re: TreeView und ListView
 
Entweder bin ich zu doof um die Funktion umzubauen oder die tut einfach nicht das was ich möchte.

Jetzt zeigt er mir im TreeView nichts mehr an und im ListView zeigt er mir ALLES an.

also Ordner + unterordner + dateiname

und dabei listet er die Ordner und Unterordner auch einzeln auf.

z.B.: C:\
C:\Test
C:\Test\test.txt

Hat jemand ne Lösung?

Hier meine umgebaute Funktion:
Delphi-Quellcode:
procedure TForm2.FindAllFiles(FileList: TListView;
                              RootFolder: string;
                              Mask: string ='*';
                              Recurse: Boolean = True;
                              AddFolderNames: Boolean = False;
                              IgnoreMaskAtFolderNames: Boolean = True);
  procedure LFindAllFiles(AParentFolder: String);
  var LSearchRec: TSearchRec;
  begin
    if FindFirst(AParentFolder + '*', faAnyFile, LSearchRec) = 0 then
    begin
      repeat
        if (LSearchRec.Name <> '.') and (LSearchRec.Name <> '..') then
        begin
          if LSearchRec.Attr and faDirectory = faDirectory then
          begin
            if AddFolderNames and
               (IgnoreMaskAtFolderNames or Like(AnsiLowerCase(LSearchRec.Name), Mask)) then
              FileList.AddItem(AParentFolder + LSearchRec.Name, TObject(True));
            if Recurse then
              LFindAllFiles(AParentFolder + LSearchRec.Name + '\');
          end
          else if Like(AnsiLowerCase(LSearchRec.Name), Mask) then
            FileList.AddItem(AParentFolder + LSearchRec.Name, TObject(False));
        end;
      until FindNext(LSearchRec) <> 0;
      FindClose(LSearchRec);
    end;
  end;
begin
  Mask := AnsiLowerCase(Mask);
  LFindAllFiles(IncludeTrailingPathDelimiter(RootFolder));
end;
Ich vermute einfach mal das
Delphi-Quellcode:
FileList.AddItem(AParentFolder + LSearchRec.Name, TObject(True));
auf keinen Fall so richtig ist. Aber wie komm ich an
Delphi-Quellcode:
AddObject
???

Malte Koch 13. Sep 2007 15:30

Re: TreeView und ListView
 
Hab es endlich richtig hinbekommen. Danke für die Hilfe

Mackhack 13. Sep 2007 15:33

Re: TreeView und ListView
 
Dann immer her mit dem funktionierenden Code damit alle was davon haben!


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz