Создайте точную копию TPanel на Delphi5

У меня есть TPanel pnlMain, где создаются несколько динамических TPanel (а pnlMain является их родителем) в соответствии с действиями пользователя, проверкой данных и т. Д. Каждая панель содержит одну цветную сетку, полную строк. Помимо панелей, есть несколько компонентов стрелок с открытым исходным кодом и изображение. Целая куча вещей.

Теперь я хочу, чтобы пользователь мог печатать эту панель (я спросил, как это сделать по этому вопросу), но перед печатью пользователю должна быть представлена ​​новая форма, содержащая копию pnlMain. В этой форме пользователь должен внести некоторые изменения, добавить несколько компонентов, а затем распечатать свою настроенную копию pnlMain. После печати пользователь закроет эту форму и вернется к исходной форме с оригинальным pnlMain. И - как вы можете догадаться - оригинальный pnlMain должен оставаться неизменным.

Так есть ли какой-нибудь умный способ скопировать весь TPanel и его содержимое? Я знаю, что могу сделать это вручную, перебирая список pnlMain.Controls.

3 ответа

Решение

Код основан на итерации дочерних элементов управления, но в любом случае не плох;-)

procedure TForm1.btn1Click(Sender: TObject);

    function CloneComponent(AAncestor: TComponent): TComponent;
      var
        XMemoryStream: TMemoryStream;
        XTempName: string;
      begin
        Result:=nil;
        if not Assigned(AAncestor) then
          exit;
        XMemoryStream:=TMemoryStream.Create;
        try
          XTempName:=AAncestor.Name;
          AAncestor.Name:='clone_' + XTempName;
          XMemoryStream.WriteComponent(AAncestor);
          AAncestor.Name:=XTempName;
          XMemoryStream.Position:=0;
          Result:=TComponentClass(AAncestor.ClassType).Create(AAncestor.Owner);
          if AAncestor is TControl then TControl(Result).Parent:=TControl(AAncestor).Parent;
          XMemoryStream.ReadComponent(Result);
        finally
          XMemoryStream.Free;
        end;
      end;

    var
      aPanel: TPanel;
      Ctrl, Ctrl_: TComponent;
      i: integer;
    begin
      //handle the Control (here Panel1) itself first
      TComponent(aPanel) := CloneComponent(pnl1);
      with aPanel do
      begin
        Left := 400;
        Top := 80;
      end;

      //now handle the childcontrols
      for i:= 0 to pnl1.ControlCount-1 do begin
        Ctrl := TComponent(pnl1.Controls[i]);
        Ctrl_ := CloneComponent(Ctrl);
        TControl(Ctrl_).Parent := aPanel;
        TControl(Ctrl_).Left := TControl(Ctrl).Left;
        TControl(Ctrl_).top := TControl(Ctrl).top;
      end;
    end;

код из статьи Delphi3000

Слишком много кода... ObjectBinaryToText и ObjectTextToBinary прекрасно выполняют свою работу, используя потоковую передачу. В Delphi 7 есть пример кода, но я не знаю, что 2009 (или 2006, никогда не удосужившийся взглянуть) по-прежнему есть. См. Файл справки D5 для этих функций (здесь нет d5).

Я бы сделал это с помощью RTTI, чтобы скопировать все свойства. Вам все равно придется перебирать все элементы управления, но когда вам нужно настроить значения свойств, RTTI может помочь автоматизировать процесс. Вы можете получить пример в конце этой статьи, где вы найдете ссылку на некоторый вспомогательный код, включая CopyObject рутина.

Другие вопросы по тегам