Copy dynamically a TTabSheet to another lazarus / 31-LCL ---------------------------------------------------------------------- simsee · 2016-11-21 14:29 Dear all, I have a TPageControl with inside some TTabSheet created dinamically by user at run time. Each tab contains (is parent of) a TCustomControl. I want to allow user to copy the content of a tab to anther already existing. I made some attempt, without success... Can someone give me an hint? Thanks! ---------------------------------------------------------------------- guest58172 · 2016-11-21 16:22 Classes are references types so a copy is just a copy of the pointer that will still lead to the same heap instance. In Object Pascal, Assign() is the idiomatic way to have value semantic with objects. However this will only work with a subclass of your own. Also the copy is programmed manually, field by field (this is often a source of error, e.g when class fields are added, assign() must be updated too). Typically: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i TFoo = class(TPersistent)    procedure assign(source: TPersistent); override;end; procedure TFoo.assign(source: TPersistent);begin  if source is TFoo then  begin    // (deep) copy from TFoo(source)  end  else inherited;end; ---------------------------------------------------------------------- derek.john.evans · 2016-11-21 17:14 There is a Delphi thread here with code which works in Lazarus: http://stackoverflow.com/questions/239002/duplicating-components-at- run-time Here is a cleaned up version to copy controls from a TWinControl to another TWinControl: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses TypInfo; procedure ControlCopyProperties(const ASrc, ADst: TControl);var  LMemoryStream: TMemoryStream;begin  LMemoryStream := TMemoryStream.Create;  try    LMemoryStream.WriteComponent(ASrc);    LMemoryStream.Position := 0;    LMemoryStream.ReadComponent(ADst);  finally    LMemoryStream.Free;  end;end; procedure ControlCopyEvents(const ASrc, ADst: TControl);var  LIndex: integer;  LPropList: TPropList;begin  for LIndex := 0 to GetPropList(ASrc.ClassInfo, [tkMethod], @LPropList) - 1 do begin    SetMethodProp(ADst, LPropList[LIndex], GetMethodProp(ASrc, LPropList[LIndex]));  end;end; procedure WinControlCopyControls(const ASrc: TWinControl; const ADst: TWinControl;  const ACopyEvents: boolean = True);var  LIndex: integer;  LSrcControl, LDstControl: TControl;begin  for LIndex := ASrc.ControlCount - 1 downto 0 do begin    LSrcControl := ASrc.Controls[LIndex];    LDstControl := TControlClass(LSrcControl.ClassType).Create(ADst);    LDstControl.Parent := ADst;    ControlCopyProperties(LSrcControl, LDstControl);    LDstControl.Name := LSrcControl.Name;    if ACopyEvents then begin      ControlCopyEvents(LSrcControl, LDstControl);    end;  end;end; The method seems to work for TTreeViews but not TListViews. Simple controls like TEdit/TMemo/TCheckBox/TButton work ---------------------------------------------------------------------- simsee · 2016-11-21 17:32 Thanks to all for deep responses... My question arises from the problem of having floating tab inside a TPageControl... I need to copy a tab in order to copy it. May be there is a better solution to this problem... Has anyone implemented this feature? ---------------------------------------------------------------------- guest58172 · 2016-11-21 17:38 Try to post a minimal example that shows the issue. Without specific details you can't have a specific answer. ---------------------------------------------------------------------- simsee · 2016-11-21 18:03 I try to explain better... This is a simplified snipped of my code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses USimpleGraph, .... ...type  TMainForm = class(TForm)  ...    TabContainer: TPageControl;    ...  procedure MenuNewClick(Sender: TObject);  ...  end; ...    procedure TMainForm.MenuNewClick(Sender: TObject); //create new tabvar  NewTab : TTabSheet;  NewGraph : TEvsSimpleGraph;   begin  NewTab:=TTabSheet.Create(TabContainer);   NewTab.PageControl:=TabContainer;         ....    NewGraph:=TEvsSimpleGraph.Create(NewTab);  NewGraph.Parent:=NewTab;  ....end; TEVSSimpleGraph is a TCustomControl defined in a third party component (https://sourceforge.net/projects/evssimplegraph/). How can I allow user to move tab (i.e. as in lazarus editor)? Thanks again for the help! ---------------------------------------------------------------------- derek.john.evans · 2016-11-21 18:15 Quote from: simsee on November 21, 2016, 07:03:38 pmHow can I allow user to move tab (i.e. as in lazarus editor)? Do you mean drag and drop tab? ie: Reordering the tabs? ---------------------------------------------------------------------- derek.john.evans · 2016-11-21 18:31 Im heading out. Ignore post if it isn't what you want. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormCreate(Sender: TObject);begin  PageControl1.DragMode := dmAutomatic;end; procedure TForm1.PageControl1DragDrop(Sender, Source: TObject; X, Y: integer);var  LPageIndex: integer;begin  with Sender as TPageControl do begin    LPageIndex := IndexOfTabAt(X, Y);    if LPageIndex < 0 then begin      LPageIndex := PageCount - 1;    end;  ActivePage.PageIndex := LPageIndex;  end;end; procedure TForm1.PageControl1DragOver(Sender, Source: TObject; X, Y: integer;  State: TDragState; var Accept: boolean);begin  Accept := Sender is TPageControl;end; ---------------------------------------------------------------------- simsee · 2016-11-21 18:34 Yes, I mean that. Now I study your solution. May be I understand! ---------------------------------------------------------------------- simsee · 2016-11-21 19:58 I did some experiment. The problema with the proposed solution is that the content does not follow the dragged tab... ---------------------------------------------------------------------- howardpc · 2016-11-21 21:31 The attached example shows how you can copy a TCustomControl (shown as a green rectangle) from Tabsheet1 to another tab, chosen from a list; though I'm not sure whether this is what you want to do or not. Here the copy is done by a sequence of property copies from one control to the other. In proper code you would override the Assign method of your actual custom control and use the overridden Assign() method. ---------------------------------------------------------------------- simsee · 2016-11-21 22:10 Thanks Howard. Curious coincidence: I'm just reading your book to better understand concept related to this topic  . With the help of this forum I think now I have found the solution to my problem. ---------------------------------------------------------------------- simsee · 2016-11-23 13:06 I apologize for the follow up of thread... A last question: With the Geepster solution, when I simply click on a tab to select it, not to start a drag&drop operation, the mouse cursor automatically change with the shape of drag&drop mode. I know this behavior depends of dragmode set to dmAutomatic. But if I set this to dmManual, how can I activate a drag&drop operation with the StartDrag method? Thanks again!