Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Clone VLC-controls at runtime

229 views
Skip to first unread message

John Schmidt

unread,
Aug 22, 2006, 5:22:08 AM8/22/06
to

Hello,

How can I clone a VCL-control at runtime on a simple way - without copying each property one per one? Something with RTTI perhaps? How to proceed if RTTI?

Thanks,
John

Remy Lebeau (TeamB)

unread,
Aug 22, 2006, 2:12:51 PM8/22/06
to

"John Schmidt" <john.s...@js-computing.com> wrote in message
news:44eaccc0$1...@newsgroups.borland.com...

> How can I clone a VCL-control at runtime on a simple way - without
> copying each property one per one?

You can't. The VCL is not set up for cloning.

> Something with RTTI perhaps?

That still requires you to copy properties one at a time, and even then only
published properties can be copied with RTTI.

> How to proceed if RTTI?

Look at the TypInfo unit. There are tons of functions in it for working
with RTTI. You would basically need to get a list of the published
properties, and then copy their values from one object instance to another
one at a time.


Gambit

John Schmidt

unread,
Aug 22, 2006, 3:43:37 PM8/22/06
to

>You can't. The VCL is not set up for cloning.

But how does it the IDE? There too, you can just copy a control with all it's properties except the name of course. It's hard to believe that Borland has resolved it by one-by-one-copy of the properties, not to speak about the private ones...

John

Mike Shkolnik

unread,
Aug 22, 2006, 3:43:32 PM8/22/06
to
You may use the Assign method but most third-party components don't
implement this method.
--
With best regards, Mike Shkolnik
E-mail: mshk...@scalabium.com
WEB: http://www.scalabium.com

"John Schmidt" <john.s...@js-computing.com> wrote in message
news:44eaccc0$1...@newsgroups.borland.com...
>

Florent Ouchet

unread,
Aug 22, 2006, 3:59:25 PM8/22/06
to
Hi,

John Schmidt a écrit :


> How can I clone a VCL-control at runtime on a simple way - without copying each property one per one? Something with RTTI perhaps? How to proceed if RTTI?

That's possible using streams:

procedure TForm2.Button1Click(Sender: TObject);
var
AStream: TStream;
Button3: TButton;
begin
AStream :=TMemoryStream.Create;
try
AStream.WriteComponent(Button2);
Button3 := TButton.Create(nil);
AStream.Position := 0;
AStream.ReadComponent(Button3);
Button3.Name := 'Button3';
Button3.Top := Button3.Top + 30;
Button3.Parent := Self;
finally
AStream.Free;
end;
end;

But there are lots of drawbacks:
- the owner cannot be assigned (or cannot be the same as Button2.Owner
(you cannot have 2 components having the same name for one owner)
- you have to free the component by yourself if Owner is set to nil.
- the Parent property must be assigned by hand
- the control is an exact copy, its position has to be modified by
hand, otherwise it will be displayed above the original component.
- the name property is optional, but it will make thing easier for
code using FindComponent.

The main good is that the stream can be a memory stream, a file stream,
a database stream, something stream on internet or whatever you like
that inherits from TStream.

A stream can contain more than one component stored one after the other,
if a component like TPanel has some components on it, all its childs
will be stored in the stream too (and of course cloned too).

--
Florent Ouchet

Florent Ouchet

unread,
Aug 22, 2006, 4:01:22 PM8/22/06
to
John Schmidt a écrit :

> But how does it the IDE? There too, you can just copy a control with all it's properties except the name of course. It's hard to believe that Borland has resolved it by one-by-one-copy of the properties, not to speak about the private ones...

The IDE uses streams and text stored in the clipboard, the method I
suggested in the other post. In order to see that, you may copy a
component on the form designer, open notepad and paste the text.

--
Florent Ouchet

Remy Lebeau (TeamB)

unread,
Aug 22, 2006, 7:06:53 PM8/22/06
to

"Florent Ouchet" <ouchet....@laposte.net> wrote in message
news:44eb...@newsgroups.borland.com...

> - the owner cannot be assigned (or cannot be the same as Button2.Owner

Yes, it can:

Button2.Owner.InsertComponent(Button3);

Alternatively, use TReader directly. Then you can set its Owner and Parent
properties, which will in turn be assigned to any components read from the
stream.

> you cannot have 2 components having the same name for one owner

That is true. But if you delete or rename the old component, then you won't
have a problem. Even better, you usually don't need to assign a Name at all
to dynamically-created objects.

> - the Parent property must be assigned by hand

Again, you can use TReader to automate that.

> - the name property is optional, but it will make thing
> easier for code using FindComponent.

Good designs usually don't need to use FindComponent() at all.


Gambit


Remy Lebeau (TeamB)

unread,
Aug 22, 2006, 7:01:53 PM8/22/06
to

"John Schmidt" <john.s...@js-computing.com> wrote in message
news:44eb5e69$1...@newsgroups.borland.com...

> But how does it the IDE? There too, you can just copy a control
> with all it's properties except the name of course.

When a component is copied to the clipboard, a DFM representation of the
component (and thus, only its published properties) is saved to the
clipboard. When the clipboard is pasted, a new instance of the component is
instantiated and then the DFM is streamed into it in exactly the same manner
that DFMs normally operate at runtime.

> It's hard to believe that Borland has resolved it by one-by-one-copy
> of the properties

That is exactly what happens. The properties are streamed into a DFM one at
a time, then the DFM is streamed one property at a time back into the new
instance.

> not to speak about the private ones...

Private properties can only be streamed if the component manually implements
custom streaming by overriding the virtual DefineProperties() method.


Gambit

Remy Lebeau (TeamB)

unread,
Aug 22, 2006, 7:02:36 PM8/22/06
to

"Mike Shkolnik" <mshkol...@ukr.net> wrote in message
news:44eb...@newsgroups.borland.com...

> You may use the Assign method but most third-party


> components don't implement this method.

Most components in general do not implement Assign(), including Borland's
native components.


Gambit


Florent Ouchet

unread,
Aug 23, 2006, 5:04:56 AM8/23/06
to
Remy Lebeau (TeamB) a écrit :
> Button2.Owner.InsertComponent(Button3);

I Forgot this possibility :(
It would be easier to be found if the owner property was read/write.

> That is true. But if you delete or rename the old component, then you won't
> have a problem. Even better, you usually don't need to assign a Name at all
> to dynamically-created objects.

There are some unwanted side effects (at least in BDS 2006):

drop 2 buttons on a form:

procedure TForm1.Button1Click(Sender: TObject);
begin
Button2.Name := 'toto'; // or an empty string
if Assigned(Button2) then
ShowMessage('Button2 assigned')
else
ShowMessage('Button2 not assigned');
end;

Once Button2's name is changed, you cannot use Form1.Button2 to access
its instance. A local reference has to be used:

procedure TForm2.Button1Click(Sender: TObject);
var
AButton: TButton;
begin
AButton := Button2;

AButton.Name := 'toto';
if Assigned(Button2) then
ShowMessage('Button2 assigned')
else
ShowMessage('Button2 not assigned');

AButton.Name := 'Button2';
if Assigned(Button2) then
ShowMessage('Button2 assigned')
else
ShowMessage('Button2 not assigned');
end;

--
Florent Ouchet

John Schmidt

unread,
Aug 23, 2006, 7:52:14 AM8/23/06
to

"Remy Lebeau \(TeamB\)" <no....@no.spam.com> wrote:
>
>Alternatively, use TReader directly. Then you can set its Owner and Parent
>properties, which will in turn be assigned to any components read from the
>stream.

Shame on me, but I never had contact with TReader. Do you just have a very simple example how to use it?

John

John Schmidt

unread,
Aug 23, 2006, 7:54:16 AM8/23/06
to

It seems to be just what I need. - Yesterday when I checked the news, your message weren't yet there...

Thanks,
John

John Schmidt

unread,
Aug 23, 2006, 7:57:55 AM8/23/06
to

Very clever!

Peter Below (TeamB)

unread,
Aug 23, 2006, 1:47:51 PM8/23/06
to
John Schmidt wrote:

Search the newsgroup archives for CloneComponent, that should turn up a
function i posted some time ago. It shows the principle.

--
Peter Below (TeamB)
Don't be a vampire (http://slash7.com/pages/vampires),
use the newsgroup archives :
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be

John Schmidt

unread,
Aug 24, 2006, 7:10:21 AM8/24/06
to

">Search the newsgroup archives for CloneComponent, that should turn up a
>function i posted some time ago. It shows the principle.

Thanks, this would be marvellous but I din't find it. I have searched in the news and in the CodeCentral. Did they move the article perhaps?

John

Robert Wachtel

unread,
Aug 24, 2006, 9:30:20 AM8/24/06
to
Hi!

John Schmidt wrote:
> Thanks, this would be marvellous but I din't find it. I have searched in
> the news and in the CodeCentral. Did they move the article perhaps?

http://groups.google.de/groups?q=clonecomponent

hth

Robert


Peter Below (TeamB)

unread,
Aug 24, 2006, 1:47:41 PM8/24/06
to
John Schmidt wrote:

My signature below contains a number of links to newsgroup search
engines that archive the Borland newsgroup. That is what i meant by
"newsgroup archives".

0 new messages