-------------------------------------------------------- модуль Clone;
interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,Forms, Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables, Outline; function Replicator(C: TComponent): TComponent; implementation { Следующая процедура "клонирует" свойства C1 и записывает их в C2. C1 и C2 должны иметь один и тот же тип. Используйте данный метод для компонентов, не имеющих метода Assign. } procedure CloneComponent(C1: TComponent; C2: TComponent);varS: TMemoryStream;beginif C1.ClassType <> C2.ClassType thenraise EComponentError.Create('Типы объектов не совместимы');if C1 is TWinControl thenTWinControl(C2).Parent := TWinControl(C1).Parent;S := TMemoryStream.Create; { создаем поток для работы с памятью }with S do beginWriteComponent(C1); { пишем свойства C1 в поток }Seek(0, 0); { перемещаемся в начало потока }ReadComponent(C2); { читаем свойства из потока в C2 }Free; { освобождаем поток }end;end; { Следующая функция "реплицирует" компонент C и возвращает новый компонент типа и со свойствами компонента C. } function Replicator(C: TComponent): TComponent;beginResult := TComponentClass(C.ClassType).Create(C.Owner); { создаем компонент }CloneComponent(C, Result); { клонируем его }end; end. |
Вот как это использовать это:
varBitBtn: TBitBtn;beginTComponent(BitBtn) := Replicator(BitBtn1); { Если BitBtn1 уже существует }end; |
-- Xavier [000644]
Данная функция может оказаться весьма полезной в случае наличия нескольких одинаковых областей на форме с необходимостью синхронизации изменений в течение некоторого промежутка времени. Процедура создания дубликата проста до безобразия: разместите на 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 beginInc(i);Name := Format('%s%d', [tempname, i]);end;end; function DuplicateComponents( AComponent: TComponent // исходный компонент): TComponent; // возвращаемся к созданию нового компонента procedure RegisterComponentClasses(AComponent: TComponent);vari : integer;beginRegisterClass(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; tryStream := TMemoryStream.Create;RegisterComponentClasses(AComponent); tryWriter := TWriter.Create(Stream, 4096);Writer.Root := AComponent.Owner;Writer.WriteSignature;Writer.WriteComponent(AComponent);Writer.WriteListEnd;finallyWriter.Free;end; Stream.Position := 0;tryUniqueReader := 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;finallyUniqueReader.Free;end;finallyStream.Free;end;end; |