Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-10

How to clone a component

10 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

patspiper

Hi,

What is the correct way to clone programmatically a component, ie assign all its properties to another component of the same class (like the IDE designer's copy/paste)?

The code below used to work in Delphi but does not with Lazarus (result
is nil).
     RegisterClass(TMyComponent);
     Clipboard.SetComponent(MyComponent);
     Result:= TMyComponent(Clipboard.GetComponent(Self, Self));

Stephano

Reply by email

Mattias Gaertner
to patspiper
Show quoted text 11 lines
Hi, What is the correct way to clone programmatically a component, ie assign all its properties to another component of the same class (like the IDE designer's copy/paste)? The code below used to work in Delphi but does not with Lazarus (result is nil). RegisterClass(TMyComponent); Clipboard.SetComponent(MyComponent); Result:= TMyComponent(Clipboard.GetComponent(Self, Self));

It should work in Lazarus too.

Mattias

Reply by email

patspiper
to Mattias Gaertner
Mattias Gaertner wrote 15 lines
On Thu, 04 Oct 2012 00:33:07 +0300 patspiper wrote: > Hi, > > What is the correct way to clone programmatically a component, ie assign > all its properties to another component of the same class (like the IDE > designer's copy/paste)? > > The code below used to work in Delphi but does not with Lazarus (result > is nil). > RegisterClass(TMyComponent); > Clipboard.SetComponent(MyComponent); > Result:= TMyComponent(Clipboard.GetComponent(Self, Self)); It should work in Lazarus too.

It does not. It seems due to the fact that TClipboard.GetComponent uses pcfComponent while TClipboard.SetComponent uses pcfCustomData instead. Substituting pcfCustomData by pcfComponent did the job, but then the copied (original) component seems to lose its events. I will test further and report.

Stephano

Reply by email

patspiper
to patspiper
patspiper wrote 22 lines
On 04/10/12 09:19, Mattias Gaertner wrote: > On Thu, 04 Oct 2012 00:33:07 +0300 > patspiper wrote: > >> Hi, >> >> What is the correct way to clone programmatically a component, ie >> assign >> all its properties to another component of the same class (like the IDE >> designer's copy/paste)? >> >> The code below used to work in Delphi but does not with Lazarus (result >> is nil). >> RegisterClass(TMyComponent); >> Clipboard.SetComponent(MyComponent); >> Result:= TMyComponent(Clipboard.GetComponent(Self, Self)); > It should work in Lazarus too. It does not. It seems due to the fact that TClipboard.GetComponent uses pcfComponent while TClipboard.SetComponent uses pcfCustomData instead. Substituting pcfCustomData by pcfComponent did the job, but then the copied (original) component seems to lose its events. I will test further and report.

The copied (original) component's events are fine. However, it is the clone's events which are not as desired. Its methods code+data are equal to the original component's methods code+data whereas the data part should point to the clone itself for proper operation of the clone. Any ideas on how this should be handled?

Stephano

Reply by email

patspiper
to patspiper
patspiper wrote 30 lines
On 04/10/12 09:57, patspiper wrote: > On 04/10/12 09:19, Mattias Gaertner wrote: >> On Thu, 04 Oct 2012 00:33:07 +0300 >> patspiper wrote: >> >>> Hi, >>> >>> What is the correct way to clone programmatically a component, ie >>> assign >>> all its properties to another component of the same class (like the >>> IDE >>> designer's copy/paste)? >>> >>> The code below used to work in Delphi but does not with Lazarus >>> (result >>> is nil). >>> RegisterClass(TMyComponent); >>> Clipboard.SetComponent(MyComponent); >>> Result:= TMyComponent(Clipboard.GetComponent(Self, Self)); >> It should work in Lazarus too. > It does not. It seems due to the fact that TClipboard.GetComponent > uses pcfComponent while TClipboard.SetComponent uses pcfCustomData > instead. Substituting pcfCustomData by pcfComponent did the job, but > then the copied (original) component seems to lose its events. I will > test further and report. The copied (original) component's events are fine. However, it is the clone's events which are not as desired. Its methods code+data are equal to the original component's methods code+data whereas the data part should point to the clone itself for proper operation of the clone. Any ideas on how this should be handled?

I have gathered the following presumed bugs:

1- TClipboard.GetComponent uses pcfComponent while TClipboard.SetComponent uses pcfCustomData instead.

2- Clipboard.SetComponent/GetComponent do not save/restore events. Events are nil. This is the clipboard text of a button with an assigned OnClick event (note the missing OnClick):
object Button1: TButton
Left = 24
Height = 25
Top = 16
Width = 139
Caption = 'Button1'
Font.Height = -20
Font.Name = 'Sans'
ParentFont = False
TabOrder = 0
end

Stephano

Reply by email

Hans-Peter Diettrich
to patspiper: The copied (original) component's events are fine. However, it is the clone's events…
Show quoted text 5 lines
The copied (original) component's events are fine. However, it is the clone's events which are not as desired. Its methods code+data are equal to the original component's methods code+data whereas the data part should point to the clone itself for proper operation of the clone. Any ideas on how this should be handled?

I don't think that the clipboard should contain pointers, which become invalid as soon as the referenced form is closed.

The data pointer should refer to the *form* containing the cloned component. When that form doesn't have the named method, the handler reference may be cleared.

DoDi

Reply by email

Mattias Gaertner
to Hans-Peter Diettrich
Show quoted text 10 lines
patspiper schrieb: > The copied (original) component's events are fine. However, it is the > clone's events which are not as desired. Its methods code+data are equal > to the original component's methods code+data whereas the data part > should point to the clone itself for proper operation of the clone. Any > ideas on how this should be handled? I don't think that the clipboard should contain pointers, which become invalid as soon as the referenced form is closed.

The lfm stream does not contain pointers.
The reader has just the wrong root component.

The data pointer should refer to the *form* containing the cloned component. When that form doesn't have the named method, the handler reference may be cleared.

Mattias

Reply by email

Mattias Gaertner
to patspiper: I have gathered the following presumed bugs: 1- TClipboard.GetComponent uses pcfComponent…
Show quoted text 36 lines
On 04/10/12 10:45, patspiper wrote: > On 04/10/12 09:57, patspiper wrote: >> On 04/10/12 09:19, Mattias Gaertner wrote: >>> On Thu, 04 Oct 2012 00:33:07 +0300 >>> patspiper wrote: >>> >>>> Hi, >>>> >>>> What is the correct way to clone programmatically a component, ie >>>> assign >>>> all its properties to another component of the same class (like the >>>> IDE >>>> designer's copy/paste)? >>>> >>>> The code below used to work in Delphi but does not with Lazarus >>>> (result >>>> is nil). >>>> RegisterClass(TMyComponent); >>>> Clipboard.SetComponent(MyComponent); >>>> Result:= TMyComponent(Clipboard.GetComponent(Self, Self)); >>> It should work in Lazarus too. >> It does not. It seems due to the fact that TClipboard.GetComponent >> uses pcfComponent while TClipboard.SetComponent uses pcfCustomData >> instead. Substituting pcfCustomData by pcfComponent did the job, but >> then the copied (original) component seems to lose its events. I will >> test further and report. > The copied (original) component's events are fine. However, it is the > clone's events which are not as desired. Its methods code+data are > equal to the original component's methods code+data whereas the data > part should point to the clone itself for proper operation of the > clone. Any ideas on how this should be handled? I have gathered the following presumed bugs: 1- TClipboard.GetComponent uses pcfComponent while TClipboard.SetComponent uses pcfCustomData instead.

Please report this bug.

Show quoted text 14 lines
2- Clipboard.SetComponent/GetComponent do not save/restore events. Events are nil. This is the clipboard text of a button with an assigned OnClick event (note the missing OnClick): object Button1: TButton Left = 24 Height = 25 Top = 16 Width = 139 Caption = 'Button1' Font.Height = -20 Font.Name = 'Sans' ParentFont = False TabOrder = 0 end

Are you sure that Delphi SetComponent writes events?

Mattias

Reply by email

patspiper
to Mattias Gaertner
Mattias Gaertner wrote 9 lines
On Thu, 04 Oct 2012 15:08:31 +0300 patspiper wrote: > On 04/10/12 10:45, patspiper wrote: >> On 04/10/12 09:57, patspiper wrote: >> I have gathered the following presumed bugs: 1- >> TClipboard.GetComponent uses pcfComponent while >> TClipboard.SetComponent uses pcfCustomData instead. Please report this bug.

Done: http://bugs.freepascal.org/view.php?id=23060

Show quoted text 15 lines
> 2- Clipboard.SetComponent/GetComponent do not save/restore events. > Events are nil. This is the clipboard text of a button with an assigned > OnClick event (note the missing OnClick): > object Button1: TButton > Left = 24 > Height = 25 > Top = 16 > Width = 139 > Caption = 'Button1' > Font.Height = -20 > Font.Name = 'Sans' > ParentFont = False > TabOrder = 0 > end Are you sure that Delphi SetComponent writes events?

No. But I was assuming that events would be written as is the case with lfm's:
object Button1: TButton
Left = 68
Height = 25
Top = 29
Width = 75
Caption = 'Button1'
OnClick = Button1Click <---------
TabOrder = 0

   end

Stephano

Reply by email

Mattias Gaertner
to patspiper

patspiper hat am 5. Oktober 2012 um 09:56 geschrieben:

Show quoted text 37 lines
On 05/10/12 09:46, Mattias Gaertner wrote: > On Thu, 04 Oct 2012 15:08:31 +0300 > patspiper wrote: > >> On 04/10/12 10:45, patspiper wrote: >>> On 04/10/12 09:57, patspiper wrote: >>> I have gathered the following presumed bugs: 1- >>> TClipboard.GetComponent uses pcfComponent while >>> TClipboard.SetComponent uses pcfCustomData instead. > Please report this bug. Done: http://bugs.freepascal.org/view.php?id=23060 >> 2- Clipboard.SetComponent/GetComponent do not save/restore events. >> Events are nil. This is the clipboard text of a button with an assigned >> OnClick event (note the missing OnClick): >> object Button1: TButton >> Left = 24 >> Height = 25 >> Top = 16 >> Width = 139 >> Caption = 'Button1' >> Font.Height = -20 >> Font.Name = 'Sans' >> ParentFont = False >> TabOrder = 0 >> end > Are you sure that Delphi SetComponent writes events? No. But I was assuming that events would be written as is the case with lfm's: object Button1: TButton Left = 68 Height = 25 Top = 29 Width = 75 Caption = 'Button1' OnClick = Button1Click <--------- TabOrder = 0 end

The Button1Click is a method of the form or a nested frame, not the Button1. The streaming need some extra params to handle events.

Mattias

Reply by email