unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ExtCtrls, Buttons, Grids;

type
  TClass = class of TObject;
  TForm1 = class(TForm)
    Panel1: TPanel;
    ClearAllBtn: TButton;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    Label2: TLabel;
    Edit1: TEdit;
    AddBtn: TButton;
    Label3: TLabel;
    ComboBox1: TComboBox;
    Label4: TLabel;
    ListBox1: TListBox;
    ListBox2: TListBox;
    Label5: TLabel;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    GroupBox1: TGroupBox;
    Edit2: TEdit;
    CheckBox1: TCheckBox;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    RadioGroup1: TRadioGroup;
    BitBtn3: TBitBtn;
    RichEdit1: TRichEdit;
    TabSheet3: TTabSheet;
    TabSheet4: TTabSheet;
    TreeView1: TTreeView;
    StringGrid1: TStringGrid;
    TreeView2: TTreeView;
    Label1: TLabel;
    Label6: TLabel;
    procedure AddBtnClick(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ClearAllBtnClick(Sender: TObject);
    procedure BitBtn3Click(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure TreeView1Click(Sender: TObject);
    procedure TreeView2Click(Sender: TObject);
  private
    { Private declarations }
    procedure AddSubNodes(Node : TTreeNode;Cntrl: TWinControl);
    function  AddClass(NewClass:  TClass):   TTreeNode;
    function  GetNode(ClassName: string):   TTreeNode;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.AddBtnClick(Sender: TObject);
begin
with ListBox1 do
  Case ComboBox1.ItemIndex of 
   0 : begin  // в начало списка
        Items.Insert(0,Edit1.Text);
        end;
   1 : begin  // в конец списка
        Items.Add(Edit1.Text);
       end;
   2 : begin // перед текущей	 строкой
        if ItemIndex<0 then ItemIndex:=0; // Если никакая строка не выделена
        Items.Insert(ItemIndex,Edit1.Text);
       end;
   3 : begin // после текущей строки
        if ItemIndex<0 then ItemIndex:=0; // Если никакая строка не выделена
        Items.Insert(ItemIndex+1,Edit1.Text);
       end;
   end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  I: Integer;
begin
 if ListBox1.Items.Count=0 then begin // Список 1 пуст
  ShowMessage('Список 1 пуст!');
  exit;
 end;
 if ListBox1.ItemIndex<0 then begin  // В Списке 1 нет выбранной строки
  ShowMessage('Выберите строку в Списке 1');
  exit;
 end;
// Добавление строки из Списка 1 в конец Списка 2
 ListBox2.Items.Add(ListBox1.Items[ListBox1.itemIndex]);
 ListBox2.ItemIndex:=ListBox2.Items.Count-1; // Текущей становится вставленная строка

 // Запоминаем и изменяем позицию текущей строки в Списке 1, т.к. скопированная строка
// будет удалена
 i:=ListBox1.ItemIndex;
 if i=(ListBox1.Items.Count-1) then  // Если скопирована последняя строка
   ListBox1.ItemIndex:=i-1
  else  ListBox1.ItemIndex:=i+1;
 ListBox1.Items.Delete(i); // Удаление скопированной строки из Списка 1
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
 if ListBox1.Items.Count=0 then begin // Список 1 пуст
  ShowMessage('Список 1 пуст!');
  exit;
 end;

 ListBox2.Items.Text := ListBox2.Items.Text + ListBox1.Items.Text;
 ListBox1.Items.Clear;
end;

procedure TForm1.Button5Click(Sender: TObject);
var
  I: Integer;
begin
 if ListBox2.Items.Count=0 then begin // Список 1 пуст
  ShowMessage('Список 2 пуст!');
  exit;
 end;
 if ListBox2.ItemIndex<0 then begin  // В Списке 1 нет выбранной строки
  ShowMessage('Выберите строку в Списке 2');
  exit;
 end;
// Добавление строки из Списка 1 в конец Списка 2
 ListBox1.Items.Add(ListBox2.Items[ListBox2.itemIndex]);
 ListBox1.ItemIndex:=ListBox1.Items.Count-1; // Текущей становится вставленная строка

 // Запоминаем и изменяем позицию текущей строки в Списке 1, т.к. скопированная строка
// будет удалена
 i:=ListBox2.ItemIndex;
 if i=(ListBox2.Items.Count-1) then  // Если скопирована последняя строка
   ListBox2.ItemIndex:=i-1
  else  ListBox2.ItemIndex:=i+1;
 ListBox2.Items.Delete(i); // Удаление скопированной строки из Списка 1
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
 if ListBox2.Items.Count=0 then begin // Список 1 пуст
  ShowMessage('Список 2 пуст!');
  exit;
 end;

 ListBox1.Items.Text := ListBox1.Items.Text + ListBox2.Items.Text;
 ListBox2.Items.Clear;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.ItemIndex := 0;
  AddSubNodes(TreeView1.Items[0],Form1);
  StringGrid1.Cells[0,0] := 'Name';
  StringGrid1.Cells[0,1] := 'Type';
  StringGrid1.Cells[0,2] := 'Size';
  StringGrid1.Cells[0,3] := 'Top';
  StringGrid1.Cells[0,4] := 'Left';
  StringGrid1.Cells[0,5] := 'Width';
end;

procedure TForm1.ClearAllBtnClick(Sender: TObject);
begin
  Edit1.Text := '';
  Edit2.Text := '';
  ListBox1.Items.Clear;
  ListBox2.Items.Clear;
  ComboBox1.ItemIndex := 0;
  RadioGroup1.ItemIndex := 0;
  RichEdit1.Clear;
  CheckBox1.Checked:=false;
end;

procedure TForm1.BitBtn3Click(Sender: TObject);
begin
  case RadioGroup1.ItemIndex of
   0 : RichEdit1.Text:=AnsiLowerCase(RichEdit1.Text);
   1 : RichEdit1.Text:=AnsiUpperCase(RichEdit1.Text);
  end;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  StartPos,ToEnd,FoundAt: Integer;
begin
  with RichEdit1 do
  begin
    { Поиск начинается с текущей позиции курсора в тексте.  
      Если курсора нет , то с перовй позиции }
    if SelLength > 0 then   // Длина выделенного фрагмента текста
      StartPos := SelStart + SelLength
    else
      StartPos := 0;
    { SelStart - начало выделенного фрагмента в тексте
      StartPos - позиция, с которой начинается поиск
      ToEnd - количество символов, которые необходимо просмотреть}

    ToEnd := Length(Text) - StartPos;

    if CheckBox1.Checked then  // с учетом регистра символов
     FoundAt := FindText(Edit2.Text, StartPos, ToEnd, [stMatchCase])  // метод поиска строки
    else
     FoundAt := FindText(Edit2.Text, StartPos, ToEnd, []);
     // FoundAt - позиция начала найденной строки в тексте
    if FoundAt <> -1 then
    begin
      // Выделение в тексте найденного фрагмента
      SetFocus;
      SelStart := FoundAt;
      SelLength := Length(Edit2.Text);
      // Активизация/деактивизация кнопок поиска
      BitBtn1.Enabled:=false;
      BitBtn2.Enabled:=true;
    end
    else begin
      ShowMessage('Строка не найдена. Задайте начальную позицию и повторите поиск.');
      // Активизация/деактивизация кнопок поиска
      BitBtn1.Enabled:=true;
      BitBtn2.Enabled:=false;
    end;
  end;
end;

procedure TForm1.AddSubNodes(Node: TTreeNode; Cntrl: TWinControl);
var
 i : integer;
 NewNode : TTreeNode;
 s : string;
 MyClass: TClass;
begin
 // Построение фрагмента дерева элементов управления, непосредственно подчиненных
 // элементу управления Cntrl
 with Cntrl do
  for i:=0 to ControlCount-1 do begin  //ControlCount - счетчик элементов управления
   // Создание узла, соответствующего элементу управления Cntrl
   if Controls[i].Name='' then s:='<без имени>'
   else s:=Controls[i].Name;
   NewNode:=TreeView1.Items.AddChildObject(Node,s,Controls[i]);
   // Добавить в дерево иерархии классов узел для типа объекта Controls[i]
   MyClass:= Controls[i].ClassType;  // Получение ссылки на класс
   AddClass(MyClass);
   // Если элемент управления типа TWinControl, то он может содержать другие элементы управления,
   // которые необходимо включить в дерево
   if Controls[i] is TWinControl then
    AddSubNodes(NewNode,Controls[i] as TWinControl);
 end;
end;

function TForm1.AddClass(NewClass: TClass): TTreeNode;
var
 ParentNode:   TTreeNode;
begin
// если класс не там ...
 Result := GetNode(NewClass.ClassName);
 if Result =  nil then begin
 // поиск родителя (с добавлением его в конечном счете)
  if NewClass.ClassParent<>nil then begin
   ParentNode := AddClass(NewClass.ClassParent) ;
   // добавление нового класса
   Result := TreeView2.Items.AddChildObject(ParentNode,NewClass.ClassName,Pointer(NewClass));
  end
  else
   // добавление нового класса как корневого узла
   Result := TreeView2.Items.AddChildObject(nil,NewClass.ClassName,Pointer(NewClass));
 end;
end;

function TForm1.GetNode(ClassName: string): TTreeNode;
var
 Node1    : TTreeNode;
begin
 // Поиск узла, соответсвующего классу
 Result:= nil; // не найден
 // поиск узла в дереве
 Node1:= TreeView2.Items.GetFirstNode;
 while Node1 <> nil do begin
  if Node1.Text = ClassName then begin
   Result := Node1;
   Exit;
  end;
  Node1:= Node1.GetNext;
 end;
end;

procedure TForm1.TreeView1Click(Sender: TObject);
var
  Node: TTreeNode;
  I: Integer;
begin
  Node := TreeView1.Selected;
  StringGrid1.Cells[1,0] := Node.Text;
  for i:=0 to Form1.componentcount-1 do
    if Form1.Components[I].Name=Node.Text then
    begin
      StringGrid1.Cells[1,1] := Form1.Components[I].ClassName;
      StringGrid1.Cells[1,2] := IntToStr(Form1.Components[I].InstanceSize)+' байт';
      StringGrid1.Cells[1,3] := IntToStr((Form1.Components[I] as TControl).Top);
      StringGrid1.Cells[1,4] := IntToStr((Form1.Components[I] as TControl).Left);
      StringGrid1.Cells[1,5] := IntToStr((Form1.Components[I] as TControl).Width);
      exit;
    end;
end;

procedure TForm1.TreeView2Click(Sender: TObject);
var
  Node: TTreeNode;
begin
  Node := TreeView2.Selected;
  Label1.Caption := 'Имя ' + TClass(Node.Data).ClassName;
  Label6.Caption := 'Размер ' + IntToStr(TClass(Node.Data).InstanceSize) + ' байт';
end;

end.
