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
> 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
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
"John Schmidt" <john.s...@js-computing.com> wrote in message
news:44eaccc0$1...@newsgroups.borland.com...
>
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
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
> - 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
> 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
> 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
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
Shame on me, but I never had contact with TReader. Do you just have a very simple example how to use it?
John
Thanks,
John
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
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
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
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".