Клонирование объектов

Создать копию объекта в Delphi очень просто. Конвертируем объект в текст, а затем - обратно. При этом будут продублированы все свойства, кроме ссылок на обработчики событий. Для преобразования компонента в файл и обратно нам понадобятся функции потоков WriteComponent(TComponent) и ReadComponent(TComponent). При этом в поток записывается двоичный ресурс. Последний с помощью функции ObjectBinaryToText можно преобразовать в текст.
Создадим на их основе функции преобразования:


function ComponentToString(Component: TComponent): string;   
var   
  ms: TMemoryStream;   
  ss: TStringStream;   
begin   
  ss := TStringStream.Create(' ');   
  ms := TMemoryStream.Create;   
  try   
    ms.WriteComponent(Component);   
    ms.position := 0;   
    ObjectBinaryToText(ms, ss);   
    ss.position := 0;   
    Result := ss.DataString;   
  finally   
    ms.Free;   
    ss.free;   
  end;   
end;   
   
procedure StringToComponent(Component: TComponent; Value: string);   
var   
  StrStream:TStringStream;   
  ms: TMemoryStream;   
begin   
  StrStream := TStringStream.Create(Value);   
  try   
    ms := TMemoryStream.Create;   
    try   
      ObjectTextToBinary(StrStream, ms);   
      ms.position := 0;   
      ms.ReadComponent(Component);   
    finally   
      ms.Free;   
    end;   
  finally   
    StrStream.Free;   
  end;   
end;  

С помощью пары этих функций мы можем преобразовать любой компонент в текст, а затем проинициализировать другой компонент того же класса этими данными.
Ниже приведен ресурс формы с одной кнопкой и текст обработчика нажатия на эту кнопку.


object Form1: TForm1   
  Left = 262   
  Top = 129   
  Width = 525   
  Height = 153   
  Caption = 'Form1'   
  Color = clBtnFace   
  Font.Charset = DEFAULT_CHARSET   
  Font.Color = clWindowText   
  Font.Height = -11   
  Font.Name = 'MS Sans Serif'   
  Font.Style = []   
  OldCreateOrder = False   
  Scaled = False   
  PixelsPerInch = 96   
  TextHeight = 13   
  object Button1: TButton   
    Left = 16   
    Top = 32   
    Width = 57   
    Height = 49   
    Caption = 'Caption'   
    TabOrder = 0   
    OnClick = Button1Click   
  end   
end   
   
procedure TForm1.Button1Click(Sender: TObject);   
var   
  Button: TButton;   
  OldName: string;   
begin   
  Button := TButton.Create(self);   
   
  //...сохраняем имя компонента   
  OldName := (Sender as TButton).Name;   
   
  //...стираем имя компонента, чтобы избежать конфликта имен.  
  //...После этого Button1 станет = nil.   
  (Sender as TButton).Name := '';   
   
  //...преобразуем в текст и обратно   
  StringToComponent( Button, ComponentToString(Sender as TButton) );   
   
  //...дадим компоненту уникальное(?) имя   
  Button.Name := 'Button' + IntToStr(random(1000));   
   
  //...вернем исходному компоненту имя.  
  //...После этого Button1 станет снова указывать на объект.   
  (Sender as TButton).Name := OldName;   
   
  //...размещаем новую кнопку справа от исходной   
  Button.parent := self;   
  Button1.Tag := Button1.Tag + 1;   
  Button.Left := Button.Left + Button.Width * Button1.Tag + 1;   
end;  

Приведенный метод не дублирует указатели на обработчики событий. Однако, если таким образом дублировать формы, то все дочерние компоненты и все обработчики сохранятся.
Теги:
объекты
Добавлено: 02 Августа 2018 07:42:51 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...