Дублирование компонентов и их потомков во время выполнения приложения
Учитывая пожелания пользователей, фирма Microsoft объявила, что она внесёт изменение в название Windows 2000, теперь эта операционная система будет называться Windows 2000 beta ДВАДЦАТЬ ПЯТЬ. P.S. (А чё? Ведь существует-же W2000 beta 3 RELEASE CANDIDATE 1)
Приведенный ниже код содержит функцию 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;
implementationprocedure TUniqueReader.ComponentRead(Component: TComponent);
begin
LastRead := Component;
end;
// Задаем уникальное имя считываемому компоненту, например,// "Panel2", если "Panel1" уже существуетprocedure TUniqueReader.SetNameUnique(
Reader: TReader;
Component: TComponent; // Считываемый компонентvar Name: string// Имя компонента для дальнейшей модификации
);
var
i: Integer;
tempname: string;
begin
i := 0;
tempname := Name;
while Component.Owner.FindComponent(Name) <> nildobegin
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 thenif TWinControl(AComponent).ControlCount > 0 thenfor 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
Writer := 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;
Дублирование компонентов и их потомков во время выполнения приложения позволяет клонировать любые компоненты и их потомки, создавая новые компоненты с теми же родителями, владельцами и именами, что и originals.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.