Page 1 of 1

How to save a form with VCL controls on it

PostPosted: Wed Jan 22, 2020 2:29 am
by maksim_volodin
What are practices for saving and opening a form with VCL controls on it?
I used this code for saving
Code: Select all
 
   TFileStream* FS = new TFileStream(File, fmCreate);
   for(int i=0;i<CompositeBeamMainForm->ComponentCount;++i)
        FS->WriteComponent(CompositeBeamMainForm->Components[i]);
   delete(FS);

and this code for opening
Code: Select all
     TFileStream* FS = new TFileStream(FileDir_Name, fmOpenRead);
     for(int i=0;i<CompositeBeamMainForm->ComponentCount;++i)
      FS->ReadComponent(CompositeBeamMainForm->Components[i]);
    delete(FS);

then I got warnings "Class TToolButton not found" and "Class TTabSheet not found".
After investigating Internet, I made registrations of those classes in VCL stream system as follows:
Code: Select all
     TComponentClass classes[2] = {__classid(TToolButton),__classid(TTabSheet)};
     RegisterClasses(classes, 1);

The warnings mentioned above were gone but the new one appears when I try to open saved files second time. "A component named ToolButton1 already exists".
What is the reason for this message? How to avoid it? Are there better ways to save forms?

Re: How ta save a form with VCL controls on it

PostPosted: Fri Jan 24, 2020 12:17 pm
by rlebeau
Rather than writing/reading the individual components, try writing/reading just the TForm itself instead. And make sure you clear the TForm of any components before you read the stream, as the reading will create new instances of the child controls that are stored in the stream, which is why you are getting "already exists" errors.

Also, you should not have to register the component classes manually, they should already be registered at program startup, or else your TForm would have failed to stream in from its main DFM resource to begin with.

Re: How ta save a form with VCL controls on it

PostPosted: Sat Jan 25, 2020 2:19 pm
by maksim_volodin
How would you recommend to clear the TForm of any components?

Re: How ta save a form with VCL controls on it

PostPosted: Sun Jan 26, 2020 1:29 pm
by HsiaLin
Just save the form it should save it all.

Re: How ta save a form with VCL controls on it

PostPosted: Sun Jan 26, 2020 9:40 pm
by rlebeau
maksim_volodin wrote:How would you recommend to clear the TForm of any components?


Loop through the Form's Components[] list delete'ing them all.

Re: How ta save a form with VCL controls on it

PostPosted: Mon Jan 27, 2020 3:11 am
by Ahmed Sayed
I think this mechanism is buggy in RAD Studio in general because when I try to save a third party Component
in say a file or table field and try to read the component back it always gives error whether the a certain TClass is not registered and I have to Register it with RegisterClass first. But when i do so the compiler complains about it does know what is this class for example TmyButton. So i had to add the header file in the include clauses. Even so still app gives me an access violation when i try to read the stream into component. The only way to make it work is that you have to drop the component you want to create dynamically at least once on the form that will create it. I don't why it has to be done this way maybe C++ builder is different from Delphi as usual.

Re: How ta save a form with VCL controls on it

PostPosted: Tue Jan 28, 2020 2:13 pm
by rlebeau
Ahmed Sayed wrote:I think this mechanism is buggy in RAD Studio in general


It is not buggy. It is just not really intended to be used this way.

Ahmed Sayed wrote:when I try to save a third party Component in say a file or table field and try to read the component back it always gives error whether the a certain TClass is not registered and I have to Register it with RegisterClass first.


All streamable classes need to be registered at runtime before they can be streamed. Components placed on a Form/Frame/DataModule at design-time are registered automatically at runtime before they are streamed in from a DFM resource.

Ahmed Sayed wrote:But when i do so the compiler complains about it does know what is this class for example TmyButton. So i had to add the header file in the include clauses.


Yes, if you register the class manually, then of course you have to tell the compiler what the class is.

Ahmed Sayed wrote:Even so still app gives me an access violation when i try to read the stream into component.


Then you are likely not using the streaming system correctly.

Ahmed Sayed wrote:The only way to make it work is that you have to drop the component you want to create dynamically at least once on the form that will create it. I don't why it has to be done this way maybe C++ builder is different from Delphi as usual.


There is no difference between Delphi and C++Builder in this regard. This is just how the DFM system works.

Re: How ta save a form with VCL controls on it

PostPosted: Fri Jan 31, 2020 12:59 am
by maksim_volodin
It is not buggy. It is just not really intended to be used this way.

To conclude, to save data entered by a user in a file, it is not recommended to use VCL controls, as "streamable" objects as it was designed primarily for other needs, but to apply "classic" approach, that is to create a structure or a class object with data members containing content of VCL controls and to process it with FILE structure or ofstream objects or with TFileStream object calling WriteBuffer() method.
Remy, what is your preference?

Re: How ta save a form with VCL controls on it

PostPosted: Fri Jan 31, 2020 12:43 pm
by rlebeau
maksim_volodin wrote:Remy, what is your preference?


I have no preference. I have used all of those techniques. I use whatever best suits the situation.