Board index » delphi » Reloading form and owned component properties at runtime

Reloading form and owned component properties at runtime

Is it possible (read: easy) to reload all of the properties of a form and
all of its owned components at runtime. What I am hoping for is something
similar to

InitInheritedComponent(Self, TForm);

This unfortunately does not work as the streaming system seems to want to
recreate rather than just reload the components. When I dig into the VCL I
seem to get stuck at TReader.ReadProperty which seems to do most of the
work I am after, but which is alas declared private.

Has anyone found or invented a better way to handle this than coming up
with my own TReader like class?

Todd Sankey
Todd.San...@HMX.Honeywell.com

 

Re:Reloading form and owned component properties at runtime


Quote
Todd Sankey wrote:

> Is it possible (read: easy) to reload all of the properties of a form and
> all of its owned components at runtime. What I am hoping for is something
> similar to

> InitInheritedComponent(Self, TForm);

  Create yourself a TPersistentForm baseclass which all your forms can
inherit from. In it you need just a couple of methods...

Procedure TPersistentForm.ReadState(Reader ?); Override;
Begin
  Reader.OnSetName:= ReaderSetName;
  Inherited ReadState(..);
End;

Procedure TPersistentForm.ReaderSetName(Component, Name ?);
Begin
// Free any DFM loaded component, allowing the run-time
// read component to take its place

  FindComponent(Name).Free;
End;

Then you can save your form by simply calling

  aStream.WriteComponent(aForm);

and recreate it by calling

  aForm:= aStream.ReadComponent(Nil) as TForm;

Andrew

Re:Reloading form and owned component properties at runtime


I had investigated this approach. It definitely will work, but there are
three reasons I have not gone this path straight off:
  1) In this case, the constructors and destructors of some of the
components have significant side-effects that I would much rather avoid.
  2) I still have to do all the work of getting the form resource, creating
a stream, creating a reader and initializing the streaming process.
  3) While I certainly could do 2) without great difficulty, it does fairly
tightly couple with the current VCL implementation of streaming, which I
would also rather avoid.

Is there a method for streaming in the properties without creating the
components unless they do not already exist?

Andrew Stewart <astew...@strobes.co.nz> wrote in article
<358F8131.74365...@strobes.co.nz>...

Quote
> Todd Sankey wrote:

> > Is it possible (read: easy) to reload all of the properties of a form
and
> > all of its owned components at runtime. What I am hoping for is
something
> > similar to

> > InitInheritedComponent(Self, TForm);

>   Create yourself a TPersistentForm baseclass which all your forms can
> inherit from. In it you need just a couple of methods...

> Procedure TPersistentForm.ReadState(Reader ?); Override;
> Begin
>   Reader.OnSetName:= ReaderSetName;
>   Inherited ReadState(..);
> End;

> Procedure TPersistentForm.ReaderSetName(Component, Name ?);
> Begin
> // Free any DFM loaded component, allowing the run-time
> // read component to take its place

>   FindComponent(Name).Free;
> End;

> Then you can save your form by simply calling

>   aStream.WriteComponent(aForm);

> and recreate it by calling

>   aForm:= aStream.ReadComponent(Nil) as TForm;

> Andrew

Re:Reloading form and owned component properties at runtime


Quote
Todd Sankey wrote:

> I had investigated this approach. It definitely will work, but there are
> three reasons I have not gone this path straight off:

>   1) In this case, the constructors and destructors of some of the
> components have significant side-effects that I would much rather avoid.

Not much can be done about that.

Quote
>   2) I still have to do all the work of getting the form resource, creating
> a stream, creating a reader and initializing the streaming process.

You dont need to create a reader, or access the form resource. Just
these few lines do all that is required, and they can be reused:

Function LoadPersistentForm(Const FileName:String):TForm;
Begin
  With TFileStream.Create(FileName, fmOpenRead) do
    Try
      Result:= ReadComponent(Nil) as TForm;
    Finally
      Free;
    End;
End;

Procedure SavePersistentForm(Const FileName:String; Const Form:TForm);
Begin
  With TFileStream.Create(FileName, fmCreate) do
    Try
      WriteComponent(Form);
    Finally
      Free;
    End;
End;

Quote
>   3) While I certainly could do 2) without great difficulty, it does fairly
> tightly couple with the current VCL implementation of streaming, which I
> would also rather avoid.

The resultant files will always be upgradeable, ie loadable in future
versions of your application, since the properties are stored by name
only, as text. As long as you never remove any published properties from
future versions of your components you'll be okay. You can add new
properties, which will be set to their default values.

You may want to avoid streaming certain components on the form, such as
menus and popup-menus, so that you are free to modify the menu heirarchy
in future versions. Each form can handle that on a case by case basis
with some work.

Quote
> Is there a method for streaming in the properties without creating the
> components unless they do not already exist?

Probably only if you parse the file yourself using a TReader.

If the components that have major side effects in their constructors can
only exist one-to-a-form, then you could raise an exception in the
constructor if the form already has one on it, before causing the
side-effects. The streaming mechanism can be hooked relatively easily to
continue on after an 'expected' known exception has occurred.

Andrew

Other Threads