LED: array[1..10] of TLed; (10 элементов компонентного типа TLed)
При необходимости динамического создания LED-компонентов организуйте цикл, пример которого мы приводим ниже:
for counter:= 1 to 10 do begin
LED[counter]:= TLED.Create;
LED[counter].top:= …
LED[counter].Left:= …
LED[counter].Parent:= Mainform; {что-то типа этого}
end;
Если компоненты уже присутствуют на форме (в режиме проектирования), сделайте их элементами массива, например так:
leds:= 0;
for counter:= 0 to Form.Componentcount do begin
if (components[counter] is TLED) then begin
inc(leds);
LED[leds]:= TLED(components[counter]);
end
end;
Тем не менее у нас получился массив со случайным расположением LED-компонентов. Я предлагаю назначить свойству Tag каждого LED-компонента порядковый номер его расположения в массиве, а затем заполнить массив, используя это свойство:
for counter := 0 to Form.Componentcount do begin
if (components[counter] is TLED) then begin
LED[Component[counter].tag]:= TLED(components[counter]);
end
end;
Если вам нужен двухмерный массив, то для формирования индекса понадобится другая хитрость, например, хранение в свойстве Hint информации о времени создания компонентов.
Дублирование компонентов и их потомков во время выполнения приложения
Приведенный ниже код содержит функцию DuplicateComponents, позволяющую проводить клонирование любых компонентов и их потомков во время выполнения приложения. Действия ее напоминают операцию копирования/вставки (copy/paste) во время разработки приложения. Новые компоненты при создании получают тех же родителей, владельцев (в случае применения контейнеров) и имена (естественно, несколько отличающихся), что и оригиналы. В данной функции есть вероятность багов, но я пока их не обнаружил. Ошибки и недочеты могут возникнуть из-за редко применяемых специфических методов, которые, вместе с тем, могут помочь программистам, столкнувшимися с аналогичными проблемами.
Данная функция может оказаться весьма полезной в случае наличия нескольких одинаковых областей на форме с необходимостью синхронизации изменений в течение некоторого промежутка времени. Процедура создания дубликата проста до безобразия: разместите на TPanel или на другом родительском компоненте необходимые элементы управления и сделайте: "newpanel := DuplicateComponents(designedpanel)".
uses SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, IniFiles, TypInfo, Debug;
type TUniqueReader = Class(TReader)
LastRead: TComponent;
procedure ComponentRead(Component: TComponent);
procedure SetNameUnique(Reader: TReader; Component: TComponent; var Name: string);
end;
implementation
procedure TUniqueReader.ComponentRead(Component: TComponent);
begin
LastRead:= Component;
end;
procedure TUniqueReader.SetNameUnique( // Задаем уникальное имя считываемому компоненту, например, "Panel2", если "Panel1" уже существует
Reader: TReader; Component: TComponent; // Считываемый компонент
var Name: string // Имя компонента для дальнейшей модификации
);
var
i: Integer;
tempname: string;
begin
i:= 0;
tempname:= Name;
while Component.Owner.FindComponent(Name) <> nil do begin
Inc(i);
Name:= Format('%s%d', [tempname, i]);
end;
end;
function DuplicateComponents(
AComponent: TComponent // исходный компонент
): TComponent; // возвращаемся к созданию нового компонента
procedure RegisterComponentClasses(AComponent: TComponent);
var i : integer;
begin
RegisterClass(TPersistentClass(AComponent.ClassType));
if AComponent is TWinControl then
if TWinControl(AComponent).ControlCount > 0 then
for i:= 0 to (TWinControl(AComponent).ControlCount-1) do RegisterComponentClasses(TWinControl(AComponent).Controls[i]);
end;
var
Stream: TMemoryStream;
UniqueReader: TUniqueReader;
Writer: TWriter;
begin
result:= nil;
UniqueReader:= nil;
Writer:= nil;
try
Stream:= TMemoryStream.Create;
RegisterComponentClasses(AComponent);
try
Write:= TWriter.Create(Stream, 4096);
Writer.Root:= AComponent.Owner;
Writer.WriteSignature;
Writer.WriteComponent(AComponent);
Writer.WriteListEnd;
finally
Writer.Free;
end;
Stream.Position:= 0;
try
UniqueReader:= TUniqueReader.Create(Stream, 4096); // создаем поток, перемещающий данные о компоненте в конструктор
UniqueReader.OnSetName:= UniqueReader.SetNameUnique;
UniqueReader.LastRead:= nil;
if AComponent is TWinControl then UniqueReader.ReadComponents( // считываем компоненты и суб-компоненты
TWinControl(AComponent).Owner, TWinControl(AComponent).Parent, UniqueReader.ComponentRead
)
else UniqueReader.ReadComponents( // читаем компоненты
AComponent.Owner, nil, UniqueReader.ComponentRead
);
result:= UniqueReader.LastRead;
finally
UniqueReader.Free;
end;
finally
Stream.Free;
end;
end;
События
Создание
Создание события во время выполнения приложения
на примере переопределения события в Memo:
memo.onchange:= memo1Change;
procedure TForm1.Memo1Change(Sender: TObject);
begin
panel1.caption:= 'Содержимое было изменено';
end;
Задержка выполнения
Задержка выполнения OnChange (Delphi 2)