Search code examples
delphitreeviewtreelazarus

Populate a TTreeView With Directory Tree And Filtering


On a Lazarus 0.9.28.2 project I have a TTreeView, with the name DirTree on my Form(frmConvert), but I want to populate it with all the directory tree, since C:\.

Like this:
C:\ Directory Tree http://i.imagehost.org/0185/cdirtree.png

And when the user select the directory, in the second TTreeView, with the name FileTree, appear all the files in that directory, but filtered to show only PDFs.

Also I want help to put these icons, because is very nice to be more organized and friendly for the end-user.

Questions

  • How can I populate the first TTreeView(DirTree) with all the directorys, like in the image?
  • How can I populate the second TTreeview(FileTree) with the files on the directory selected on DirTree?
  • How can I set a icon for each folder(only folders) on DirTree?

Solution

  • Code to populate the dirTree (REVISED)

    procedure TForm1.FormClick(Sender: TObject);
    var
      sr: TSearchRec;
      FileAttrs: Integer;
      theRootNode : tTreeNode;
      theNode : tTreeNode;
    begin
       FileAttrs := faDirectory;     // Only care about directories
       theRootNode := DirTree.Items.AddFirst(nil,'c:\');
       if FindFirst('c:\*.*', FileAttrs, sr) = 0 then
        begin
          repeat
            if (sr.Attr and FileAttrs) = sr.Attr then
            begin
                theNode := dirTree.Items.AddChild(theRootNode,sr.name);
                AddDirectories(theNode,'c:\'+sr.Name);
            end;
          until FindNext(sr) <> 0;
          FindClose(sr);
        end;
    //    DirTree.FullExpand;
    end;
    

    ****Code to populate FileTree (REVISED) ****

    procedure TForm1.FilteredTV(theDir: string;ext:String;startNode:tTreeNode);
    var
      sr: TSearchRec;
      FileAttrs: Integer;
      theNode : tTreeNode;
    begin
       if copy(ext,1,1)<>'.' then ext := '.'+ext;
       FileAttrs := faAnyfile;
       if startNode = nil then
           StartNode := FileTree.Items.AddFirst(nil,theDir);
       if FindFirst(theDir+'\*.*', FileAttrs, sr) = 0 then
        begin
          repeat
            if (sr.Attr=faDirectory) and (copy(sr.Name,1,1)<>'.') then
                begin
                    theNode := FileTree.Items.AddChild(StartNode,sr.name);
                    theNode.ImageIndex := 0;   // Use folder image for directories
                    FilteredTV(theDir+'\'+sr.name,ext,theNode);
                end
            else
                if ((sr.Attr and FileAttrs) = sr.Attr) and (ExtractFileExt(sr.name)=ext)
                then
                begin
                    theNode := FileTree.Items.AddChild(StartNode,sr.name);
                    theNode.ImageIndex := -1;   // No image for files
                end;
    
          until FindNext(sr) <> 0;
          FindClose(sr);
        end;
        FileTree.FullExpand;
    end;
    

    Additional procedure to add to form

    procedure TForm1.AddDirectories(theNode: tTreeNode; cPath: string);
    var
      sr: TSearchRec;
      FileAttrs: Integer;
      theNewNode : tTreeNode;
    begin
       FileAttrs := faDirectory;     // Only care about directories
       if FindFirst(cPath+'\*.*', FileAttrs, sr) = 0 then
        begin
          repeat
            if  ((sr.Attr and FileAttrs) = sr.Attr) and (copy(sr.Name,1,1) <> '.')
            then
            begin
                theNewNode := dirTree.Items.AddChild(theNode,sr.name);
                AddDirectories(theNewNode,cPath+'\'+sr.Name);
            end;
          until FindNext(sr) <> 0;
          FindClose(sr);
        end;
    end;
    

    You need to add an image list to your form, add a folder icon to it (there is one in the borland common files) and then associated the image list with the directory treeview and the filetree treeview

    EXAMPLE OF HOW TO CALLED FILTEREDTV procedure

    Attach the following code to the OnClick event of the directory tree

    procedure TForm1.DirTreeClick(Sender: TObject);
    var
      cBuild : string;
      theNode : tTreeNode;
    begin
        if DirTree.Selected <> nil then
        begin
            theNode := DirTree.Selected;
            cBuild := theNode.Text;
            while theNode.Parent <> nil do
            begin
                cBuild := theNode.Parent.Text+'\'+cBuild;
                theNode := theNode.Parent;
            end;
            cBuild := stringReplace(cBuild,'\\','\',[rfReplaceAll]);
            FilteredTV(cBuild,'pdf',nil);
        end;
    
    end;