unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ImgList, Search;

type
  TForm3 = class(TForm)
    tree: TTreeView;
    ImageList1: TImageList;
    procedure FormCreate(Sender: TObject);
    procedure treeExpanding(Sender: TObject; Node: TTreeNode;
      var AllowExpansion: Boolean);
  private
    procedure SetExpanded(Node: TTreeNode; isExpanded: Boolean);
    function IsExpanded(Node: TTreeNode): Boolean;
    function NodeToFolderPath(Node: TTreeNode): String;
  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation
{$R *.dfm}
var
 root:  TTreeNode;

//Устанавливает состояние элемента дерева (содержимое катагола
//зачитано или не зачитано)
procedure TForm3.SetExpanded(Node: TTreeNode; isExpanded: Boolean);
begin
  if isExpanded then
  begin
    //Подготавливаем элемент к загрузке содержимого каталога
    Node.Data := Pointer(1);
    Node.DeleteChildren;
  end
  else
  begin
    //Содержимое каталога не прочитано (или его следует обновить)
    Node.Data := Pointer(0);
    Node.Collapse(False);
    Node.DeleteChildren;
    tree.Items.AddChild(Node, ''); //Фиктивный элемент (чтобы отображался
                                   //"+", позволяющий развернуть элемент)
  end;
end;

//Возвращает True, если содержимое каталога, соответствующего элементу
//Node в дереве было ранее загружено
function TForm3.IsExpanded(Node: TTreeNode): Boolean;
begin
  IsExpanded := Integer(Node.Data) = 1;
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  //Корневой элемент дерева (диск)
  root := tree.Items.Add(tree.Items.GetFirstNode, 'C:');
  root.ImageIndex := 0;
  root.SelectedIndex := 0;
  SetExpanded(root, False);
end;

//Функция формирует полный путь каталога, соответствующего заданному
//элементу дерева
function TForm3.NodeToFolderPath(Node: TTreeNode): String;
var
  path: String;
  item: TTreeNode;
begin
  item := Node;
  while item <> nil do
  begin
    if path <> '' then
      path := item.Text + '\' + path
    else
      path := item.Text;
    item := item.Parent;
  end;
  NodeToFolderPath := path;
end;

procedure TForm3.treeExpanding(Sender: TObject; Node: TTreeNode;
                               var AllowExpansion: Boolean);
var
  strFolder: String;
  subfolders: TStrings;
  i: Integer;
  item: TTreeNode;
begin
  if not IsExpanded(Node) then
    //Содержимое каталога нужно зачитать
    SetExpanded(Node, True)
  else
  begin
    //Список подкаталогов для выделенного каталога ранее был составлен
    AllowExpansion := True;
    Exit;
  end;

  strFolder := NodeToFolderPath( Node );
  subfolders := TStringList.Create;
  if SearchInFolder(strFolder, '*', FILE_ATTRIBUTE_DIRECTORY, subfolders)
  then begin
    //Добавление в дерево элементы, соответствующие подкаталогам
    for i := 0 to subfolders.Count - 1 do
    begin
      item := tree.Items.AddChild(Node, subfolders[i]);
      item.ImageIndex := 1;
      item.SelectedIndex := 2;
      SetExpanded(item, False); //Содержимое подкаталога еще не прочитано
    end;
    AllowExpansion := True;
  end
  else
    //В каталоге нет подкаталогов
    AllowExpansion := False;

  subfolders.Free;
end;

end.
