Сегодня рассмотрим вопрос о том, как перечислить все компоненты на форме. Например, как очистить все TEdit одним циклом, как изменить надписи на всех TLabel, как нажать все TButton :)
В заметке про создание кнопок с использованием TImage я уже испольовал данный приём, теперь рассмотрим подробнее.

0. Матчасть

У объекта TForm (а также других, на которых можно поставить, например, кнопку) есть массив Components. Очевидно, так мы можем обращаться ко всем объектам на форме.
Количество объектов – свойство ComponentCount. Первый объект имеет индекс 0, последний ComponentCount-1.

1. Просто перечислим имена компонентов

Запишем в Memo, другой наглядной реализации в голову не пришло

var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do
    Memo1.Lines.Add(Components[i].Name);
end;

Теперь в Memo1 у нас имена всех компонентов.

2. Конкретизируем задачу

Будем использовать операторы is и as, тут без них никак:

var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do
    if Components[i] is TLabel then
	  Memo1.Lines.Add((Components[i] as TLabel).Caption);
end;

Вот так просто мы получили все надписи на объектах TLabel. Теперь давай сделаем их невидимыми – пусть никто не прочитает :)

var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do
    if Components[i] is TLabel then
	  (Components[i] as TLabel).Visible:=False;
end;

3. Итог

Теперь мы крутые, и нам не нужно прописывать:

Label1.Visible:=False;
Label2.Visible:=False;
...

Наконец, хочу сделать картинку к этому посту в моём delphi блоге. Я поставил на форму в случайном порядке несколько TLabel и TEdit, поставил кнопку, по нажатию на которую написал:

procedure TForm1.Button1Click(Sender: TObject);
var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do
    if Components[i] is TLabel then
	    (Components[i] as TLabel).Caption:='http://parsers.info'
    else if Components[i] is TEdit then
      (Components[i] as TEdit).Text:='crystalbit';
end;

Запустил, нажал на неё. А результат смотри в начале этого поста :)

5. Замечание

Если используешь фреймы на форме, то этот механизм может не сработать.
Спасибо Алексею Тимохину

6. Вариант с рекурсией от JayDi

Подходит для фреймов

procedure FillChildComponentsList(const SourceComponent: TComponent;
  var ChildsList: TList);
var
  I: Integer;
begin
  //рекурсивный поиск дочерних компонентов
  for I := 0 to SourceComponent.ComponentCount - 1 do
  begin
    ChildsList.Add(SourceComponent.Components[I]);
    FillChildComponentsList(SourceComponent.Components[I], ChildsList);
  end;
end;  

procedure Tf_TestFrameComponents.Button_TestComponentsClick(Sender: TObject);
var
  FoundedComponentsList: TList;
  I: Integer;
  Comp: TComponent;
begin
  //получение списка компонетов
  FoundedComponentsList := TList.Create;
  FillChildComponentsList(Self, FoundedComponentsList);  

  //смена текста у всех лейблов
  for I := 0 to FoundedComponentsList.Count - 1 do
  begin
    Comp := FoundedComponentsList[I];
    if Comp is TLabel then
    begin
      (Comp as TLabel).Caption := 'Its work!';
    end;
  end;  

  FreeAndNil(FoundedComponentsList);
end;

(c) crystalbit, http://parsers.info
а еще на блоге есть rss-лента!

P.S. сколько у меня мусора в метках, надо этим заняться

Похожие записи