unit UFind;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, Spin, ImgList, ExtCtrls;

type
  TForm1 = class(TForm)
    TreeView1: TTreeView;
    BFind: TButton;
    EDir: TEdit;
    CBInclude: TCheckBox;
    GroupBox1: TGroupBox;
    DateTimePicker1: TDateTimePicker;
    DateTimePicker2: TDateTimePicker;
    GroupBox2: TGroupBox;
    CBSize: TCheckBox;
    ComboBox1: TComboBox;
    SpinEdit1: TSpinEdit;
    Label2: TLabel;
    BBrowse: TButton;
    ImageList1: TImageList;
    Label3: TLabel;
    RGData: TRadioGroup;
    procedure BFindClick(Sender: TObject);
    procedure BBrowseClick(Sender: TObject);
    procedure TreeView1Compare(Sender: TObject; Node1, Node2: TTreeNode;
      Data: Integer; var Compare: Integer);
    procedure TreeView1DblClick(Sender: TObject);
    procedure TreeView1Collapsed(Sender: TObject; Node: TTreeNode);
    procedure TreeView1Expanded(Sender: TObject; Node: TTreeNode);
    procedure CBSizeClick(Sender: TObject);
    procedure RGDataClick(Sender: TObject);
  private
    { Private declarations }
    procedure ViewDir(Dir: string; Node: TTreeNode);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses FileCtrl, ShellAPI, DateUtils;
{$R *.dfm}

procedure TForm1.ViewDir(Dir: string; Node: TTreeNode);
// основная процедура поиска
var SR: TSearchRec;
    ires, TBegin: integer;
    NewNode, PNode: TTreeNode;
    ladd: boolean; // указывает, надо ли включать в дерево данный файл
begin
// смена каталога, чтобы не задавать полный путь к файлам
 ChDir(Dir);
// добавление узла с именем данного каталога
 PNode := TreeView1.Items.AddChild(Node, Dir);
// задание пиктограммы закрытой папки
 PNode.ImageIndex := 0;
 PNode.SelectedIndex := PNode.ImageIndex;
// начало поиска
 ires := FindFirst('*.*', faAnyFile, SR);
// вариант, учитывающий шаблон файлов
// ires := FindFirst(Dir, faAnyFile, SR);
 while ires = 0 do
 begin
  if (SR.Name <> '.') and (SR.Name <> '..')
    then begin
      ladd := true;
      if ((SR.Attr and faDirectory) <> 0) and CBInclude.Checked
// для поиска во вложенной папке рекурентный вызов ViewDir
        then ViewDir(SR.Name, PNode)
      else begin
       if ((SR.Attr and faDirectory) = 0)
        then begin
// проверка условий, наложенных на файл
// проверка даты
         case RGData.ItemIndex of
          0: TBegin := 0;
          1: TBegin := DateTimeToFileDate(Date - 7);
          2: TBegin := DateTimeToFileDate(Date - DaysInMonth(Date));
          3: TBegin := DateTimeToFileDate(Date - DaysInYear(Date));
          4: if SR.Time > DateTimeToFileDate(DateTimePicker2.Date)
             then TBegin := SR.Time + 1000
             else TBegin := DateTimeToFileDate(DateTimePicker1.Date);
         end;
         ladd := SR.Time >=  TBegin;
// проверка размера
         if not CBSize.Checked
          then if ComboBox1.ItemIndex = 0
            then ladd := ladd and (SR.Size > (SpinEdit1.Value shl 10))
            else ladd := ladd and (SR.Size < (SpinEdit1.Value shl 10));
        end;
       if ladd
       then begin
// занесение узла в дерево
        NewNode := TreeView1.Items.AddChild(PNode, SR.Name);
// задание пиктограммы
        if (SR.Attr and faDirectory) = 0
        then NewNode.ImageIndex := 1
        else NewNode.ImageIndex := 0;
        NewNode.SelectedIndex := NewNode.ImageIndex;
       end;
      end;
    end;
// продолжение поиска
  ires := FindNext(SR)
 end;
 FindClose(SR);
// возврат в предыдущий каталог
 ChDir('..');
end;

procedure TForm1.BFindClick(Sender: TObject);
// начало поиска
var Dir, CurDir: string;
begin
// запоминание текущего каталога
 CurDir := GetCurrentDir;
// очистка дерева
 TreeView1.Items.Clear;
// снятие сортировки
 TreeView1.SortType := stNone;
// корневой каталог
 Dir := Trim(EDir.Text);
 if Dir <> ''
  then if Dir[Length(Dir)] = '\'
    then Delete(Dir, Length(Dir),1);
// курсор "песочные часы"
 Screen.Cursor := crHourglass;
// уход на поиск
 ViewDir(Dir, nil);
// курсор по умолчанию
 Screen.Cursor:=crDefault;
// восстановление текущего каталога
 ChDir(CurDir);
// сортировка дерева
 TreeView1.SortType := stText;
// раскрытие корневего узла
 if TreeView1.Items[0].HasChildren
  then TreeView1.Items[0].Expand(false);
end;

procedure TForm1.BBrowseClick(Sender: TObject);
// диалог выбора каталога
var Dir: string;
begin
if SelectDirectory('Выберите папку','', Dir)
 then EDir.Text := Dir;
end;

procedure TForm1.TreeView1Compare(Sender: TObject; Node1, Node2: TTreeNode;
                                  Data: Integer; var Compare: Integer);
// функция сортировки: сначала папки, потом файлы
begin
 if Node1.ImageIndex = Node2.ImageIndex
  then Compare := AnsiCompareText(Node1.Text, Node2.Text)
  else Compare := Node1.ImageIndex - Node2.ImageIndex;
end;

procedure TForm1.TreeView1DblClick(Sender: TObject);
// открытие файла при двойном щелчке
var S: string;
    Node: TTreeNode;
begin
 Node := TreeView1.Selected;
// если это файл, а не папка
 if Node.ImageIndex = 1
 then begin
// формирование полного пути
  S := Node.Text;
  while Node.Parent <> nil do
  begin
   Node := Node.Parent;
   S := Node.Text + '\' + S;
  end;
  ShellExecute(Handle,nil,PChar(S),nil,nil,SW_SHOWNORMAL);
 end;
end;

procedure TForm1.TreeView1Collapsed(Sender: TObject; Node: TTreeNode);
// смена пиктораммы при свертывании узла папки
begin
 if(Node.ImageIndex = 2) then Node.ImageIndex := 0;
 Node.SelectedIndex := Node.ImageIndex;
end;

procedure TForm1.TreeView1Expanded(Sender: TObject; Node: TTreeNode);
// смена пиктораммы при развертывании узла папки
begin
 if(Node.ImageIndex = 0) then Node.ImageIndex := 2;
 Node.SelectedIndex := Node.ImageIndex;
end;

procedure TForm1.CBSizeClick(Sender: TObject);
// управление видимостью ComboBox1 и SpinEdit1
begin
 ComboBox1.Enabled := not CBSize.Checked;
 SpinEdit1.Enabled := not CBSize.Checked;
end;

procedure TForm1.RGDataClick(Sender: TObject);
// управление видимостью DateTimePicker1 и DateTimePicker2
begin
 DateTimePicker1.Enabled := (RGData.ItemIndex = 4);
 DateTimePicker2.Enabled := DateTimePicker1.Enabled;
end;

end.
