Sign in Join

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

Mailing lists / lazarus / 2010-05

Hook TComponent streaming system

17 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

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

Luiz Americo Pereira Camara

I'd like to set some properties of a TComponent(TForm) through RTTI before TComponent.Loaded is called.

After a call to TMyForm.Create, the component is initiated through the streaming system that calls Loaded.

Is there a way to hook this streaming system so i can change the properties before the call to Loaded?

Luiz

Reply by email

Michael Van Canneyt
to Luiz Americo Pereira Camara
Luiz Americo Pereira Camara wrote 8 lines
I'd like to set some properties of a TComponent(TForm) through RTTI before TComponent.Loaded is called. After a call to TMyForm.Create, the component is initiated through the streaming system that calls Loaded. Is there a way to hook this streaming system so i can change the properties before the call to Loaded?

You can use defineproperties for that. You can simply override it in your form and set whatever properties you want. An alternative is overriding 'Loading', which is called at the start.

Michael.

Reply by email

Luiz Americo Pereira Camara
to Michael Van Canneyt
Michael Van Canneyt wrote 17 lines
On Sat, 22 May 2010, Luiz Americo Pereira Camara wrote: > I'd like to set some properties of a TComponent(TForm) through RTTI > before TComponent.Loaded is called. > > After a call to TMyForm.Create, the component is initiated through > the streaming system that calls Loaded. > > Is there a way to hook this streaming system so i can change the > properties before the call to Loaded? You can use defineproperties for that. You can simply override it in your form and set whatever properties you want. An alternative is overriding 'Loading', which is called at the start.

Thanks. But i think that won't help me. I'm creating a instance of a generic TForm (see code below) and than setting the properties after the call to constructor.

I would need that the properties be set after loading the stored properties and before FormClass.Loaded is called but it's to late.

The problem is that Loaded is called inside the constructor call chain. I could create the instance through NewInstance but AFAIK that is too early (before creating the stored/published properties).

var
  Form: TForm;
begin
  //FormClass: TFormClass
  Form := FormClass.Create(Owner);
  SetObjectProperties(Form, FormProperties);
  [..]
end;

Luiz

Reply by email

Mattias Gaertner
to Luiz Americo Pereira Camara
Show quoted text 38 lines
Michael Van Canneyt escreveu: > > > On Sat, 22 May 2010, Luiz Americo Pereira Camara wrote: > >> I'd like to set some properties of a TComponent(TForm) through RTTI >> before TComponent.Loaded is called. >> >> After a call to TMyForm.Create, the component is initiated through >> the streaming system that calls Loaded. >> >> Is there a way to hook this streaming system so i can change the >> properties before the call to Loaded? > > You can use defineproperties for that. You can simply override it in > your > form and set whatever properties you want. An alternative is overriding > 'Loading', which is called at the start. Thanks. But i think that won't help me. I'm creating a instance of a generic TForm (see code below) and than setting the properties after the call to constructor. I would need that the properties be set after loading the stored properties and before FormClass.Loaded is called but it's to late. The problem is that Loaded is called inside the constructor call chain. I could create the instance through NewInstance but AFAIK that is too early (before creating the stored/published properties). var Form: TForm; begin //FormClass: TFormClass Form := FormClass.Create(Owner); SetObjectProperties(Form, FormProperties); [..] end;

What do you want to achieve?
Why do you think you have to set a property after loading and before Loaded?

Mattias

Reply by email

Luiz Americo Pereira Camara
to Mattias Gaertner
Mattias Gaertner wrote 28 lines
On Sat, 22 May 2010 18:33:47 -0300 Luiz Americo Pereira Camara wrote: > Thanks. But i think that won't help me. I'm creating a instance of a > generic TForm (see code below) and than setting the properties after the > call to constructor. > > I would need that the properties be set after loading the stored > properties and before FormClass.Loaded is called but it's to late. > > The problem is that Loaded is called inside the constructor call chain. > I could create the instance through NewInstance but AFAIK that is too > early (before creating the stored/published properties). > > var > Form: TForm; > begin > //FormClass: TFormClass > Form := FormClass.Create(Owner); > SetObjectProperties(Form, FormProperties); > [..] > end; > What do you want to achieve? Why do you think you have to set a property after loading and before Loaded?

Just for convenience.

Currently i'm sending a custom message to notify the form that all properties (stored in lfm plus customized) are initialized so it can take the necessary actions:

  Form.Perform(CM_INIT, 0, 0);

If i find such event/procedure i could get rid of the message sending/receiving.

Not a big issue. I still can use OnShow, CreateWnd but it would not be as intuitive as using Loaded.

Luiz

Reply by email

Michael Van Canneyt
to Luiz Americo Pereira Camara
Luiz Americo Pereira Camara wrote 43 lines
Mattias Gaertner escreveu: > On Sat, 22 May 2010 18:33:47 -0300 > Luiz Americo Pereira Camara wrote: > > >> Thanks. But i think that won't help me. I'm creating a instance of a >> generic TForm (see code below) and than setting the properties after the >> call to constructor. >> >> I would need that the properties be set after loading the stored >> properties and before FormClass.Loaded is called but it's to late. >> >> The problem is that Loaded is called inside the constructor call chain. I >> could create the instance through NewInstance but AFAIK that is too early >> (before creating the stored/published properties). >> >> var >> Form: TForm; >> begin >> //FormClass: TFormClass >> Form := FormClass.Create(Owner); >> SetObjectProperties(Form, FormProperties); >> [..] >> end; >> > > What do you want to achieve? Why do you think you have to set a property > after loading and before > Loaded? Just for convenience. Currently i'm sending a custom message to notify the form that all properties (stored in lfm plus customized) are initialized so it can take the necessary actions: Form.Perform(CM_INIT, 0, 0); If i find such event/procedure i could get rid of the message sending/receiving. Not a big issue. I still can use OnShow, CreateWnd but it would not be as intuitive as using Loaded.

What is wrong with overriding Loaded ? It is the last thing that is called ?

Michael.

Reply by email

Luiz Americo Pereira Camara
to Michael Van Canneyt
Michael Van Canneyt wrote 22 lines
On Sat, 22 May 2010, Luiz Americo Pereira Camara wrote: > Mattias Gaertner escreveu: >> What do you want to achieve? Why do you think you have to set a >> property after loading and before >> Loaded? > > Just for convenience. > > Currently i'm sending a custom message to notify the form that all > properties (stored in lfm plus customized) are initialized so it can > take the necessary actions: > > Form.Perform(CM_INIT, 0, 0); > > If i find such event/procedure i could get rid of the message > sending/receiving. > > Not a big issue. I still can use OnShow, CreateWnd but it would not > be as intuitive as using Loaded. What is wrong with overriding Loaded ? It is the last thing that is called ?

In fact i'd like to use an overrided Loaded in the created TForm. But it occurs to early:

Form := TMyForm.Create;
      [..]//Streaming system
      TMyForm.Loaded; //> occurs before the customized properties are set
MySetPropertiesFunction(Form);//Set the desired properties. Too late to
be recognized by TMyForm.Loaded

I would need :

Form := TMyForm.Create;
      [..]//Streaming system
      //hook streaming to call MySetPropertiesFunction(Form);//Set the
desired properties.
      TMyForm.Loaded; //> i can assume that all properties are set

By looking the TComponent/TReader code i could not figure how to do that, so if i did not missed something it seems is not possible.

I'll look at other solutions.

Luiz

Reply by email

Mattias Gaertner
to Luiz Americo Pereira Camara
Show quoted text 43 lines
Michael Van Canneyt escreveu: > On Sat, 22 May 2010, Luiz Americo Pereira Camara wrote: >> Mattias Gaertner escreveu: >>> What do you want to achieve? Why do you think you have to set a >>> property after loading and before >>> Loaded? >> >> Just for convenience. >> >> Currently i'm sending a custom message to notify the form that all >> properties (stored in lfm plus customized) are initialized so it can >> take the necessary actions: >> >> Form.Perform(CM_INIT, 0, 0); >> >> If i find such event/procedure i could get rid of the message >> sending/receiving. >> >> Not a big issue. I still can use OnShow, CreateWnd but it would not >> be as intuitive as using Loaded. > > What is wrong with overriding Loaded ? It is the last thing that is > called ? In fact i'd like to use an overrided Loaded in the created TForm. But it occurs to early: Form := TMyForm.Create; [..]//Streaming system TMyForm.Loaded; //> occurs before the customized properties are set MySetPropertiesFunction(Form);//Set the desired properties. Too late to be recognized by TMyForm.Loaded I would need : Form := TMyForm.Create; [..]//Streaming system //hook streaming to call MySetPropertiesFunction(Form);//Set the desired properties. TMyForm.Loaded; //> i can assume that all properties are set By looking the TComponent/TReader code i could not figure how to do that, so if i did not missed something it seems is not possible.

Why does the following not work for you?

procedure TMyForm.Loaded; override;
...
procedure TMyForm.Loaded;
begin
  MySetPropertiesFunction(Self);
  inherited Loaded;
end;

Mattias

Reply by email

Luiz Americo Pereira Camara
to Mattias Gaertner
Mattias Gaertner wrote 62 lines
On Sun, 23 May 2010 22:49:42 -0300 Luiz Americo Pereira Camara wrote: > Michael Van Canneyt escreveu: > >> On Sat, 22 May 2010, Luiz Americo Pereira Camara wrote: >> >>> Mattias Gaertner escreveu: >>> >>>> What do you want to achieve? Why do you think you have to set a >>>> property after loading and before >>>> Loaded? >>>> >>> Just for convenience. >>> >>> Currently i'm sending a custom message to notify the form that all >>> properties (stored in lfm plus customized) are initialized so it can >>> take the necessary actions: >>> >>> Form.Perform(CM_INIT, 0, 0); >>> >>> If i find such event/procedure i could get rid of the message >>> sending/receiving. >>> >>> Not a big issue. I still can use OnShow, CreateWnd but it would not >>> be as intuitive as using Loaded. >>> >> What is wrong with overriding Loaded ? It is the last thing that is >> called ? >> > In fact i'd like to use an overrided Loaded in the created TForm. But it > occurs to early: > > Form := TMyForm.Create; > [..]//Streaming system > TMyForm.Loaded; //> occurs before the customized properties are set > MySetPropertiesFunction(Form);//Set the desired properties. Too late to > be recognized by TMyForm.Loaded > > I would need : > > Form := TMyForm.Create; > [..]//Streaming system > //hook streaming to call MySetPropertiesFunction(Form);//Set the > desired properties. > TMyForm.Loaded; //> i can assume that all properties are set > > By looking the TComponent/TReader code i could not figure how to do > that, so if i did not missed something it seems is not possible. > Why does the following not work for you? procedure TMyForm.Loaded; override; ... procedure TMyForm.Loaded; begin MySetPropertiesFunction(Self); inherited Loaded; end;

Because i don't know before hand what FormClass(TMyForm) is. Also FormClass (TMyForm) does not knows FormProperties

Here's the actual code (calls a generic TForm descendant):

The article: http://lazarusroad.blogspot.com/

function ShowForm(FormClass: TFormClass; Owner: TWinControl;
FormProperties: array of const): TModalResult;
var
  Form: TForm;
begin
  Form := FormClass.Create(Owner);
  try
    SetObjectProperties(Form, FormProperties);
    Form.Perform(CM_INIT, 0, 0);
    Result := Form.ShowModal;
  finally
    Form.Destroy;
  end;
end;

Luiz

Reply by email

Mattias Gaertner
to Luiz Americo Pereira Camara
Show quoted text 5 lines
Mattias Gaertner escreveu: [...] Here's the actual code (calls a generic TForm descendant): The article: http://lazarusroad.blogspot.com/

The article does not explain why the properties must be set before calling Loaded.

Show quoted text 14 lines
function ShowForm(FormClass: TFormClass; Owner: TWinControl; FormProperties: array of const): TModalResult; var Form: TForm; begin Form := FormClass.Create(Owner); try SetObjectProperties(Form, FormProperties); Form.Perform(CM_INIT, 0, 0); Result := Form.ShowModal; finally Form.Destroy; end; end;

Mattias

Reply by email

Luiz Americo Pereira Camara
to Mattias Gaertner
Mattias Gaertner wrote 15 lines
On Sun, 23 May 2010 23:37:29 -0300 Luiz Americo Pereira Camara wrote: > Mattias Gaertner escreveu: > [...] > Here's the actual code (calls a generic TForm descendant): > > The article: http://lazarusroad.blogspot.com/ > The article does not explain why the properties must be set before calling Loaded.
If
procedure TMyForm.Loaded;
begin
  inherited;
  if MyBool then
     DoAction;
end;

MyBool will be always false even if called through

ShowForm(TMyForm, nil, ['MyBool', True]);

Luiz

Show quoted text 27 lines
> function ShowForm(FormClass: TFormClass; Owner: TWinControl; > FormProperties: array of const): TModalResult; > var > Form: TForm; > begin > Form := FormClass.Create(Owner); > try > SetObjectProperties(Form, FormProperties); > Form.Perform(CM_INIT, 0, 0); > Result := Form.ShowModal; > finally > Form.Destroy; > end; > end; > Mattias -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Mattias Gaertner
to Luiz Americo Pereira Camara
Show quoted text 24 lines
Mattias Gaertner escreveu: > On Sun, 23 May 2010 23:37:29 -0300 > Luiz Americo Pereira Camara wrote: > > >> Mattias Gaertner escreveu: >> [...] >> Here's the actual code (calls a generic TForm descendant): >> >> The article: http://lazarusroad.blogspot.com/ >> > > The article does not explain why the properties must be set before > calling Loaded. > > If procedure TMyForm.Loaded; begin inherited; if MyBool then DoAction; end;

Is this correct:
One of your forms has a design bug, which you can not fix (for whatever reason), so you need a workaround.

I see several solutions:
- Patch and compile your own special version of TReader or LCL.
- modify the lfm at runtime
- modify the VMT at runtime and override Loaded

Mattias

Reply by email

Michael Van Canneyt
to Luiz Americo Pereira Camara: If procedure TMyForm.Loaded; begin inherited; if MyBool then DoAction; end; MyBool will…
Luiz Americo Pereira Camara wrote 30 lines
Mattias Gaertner escreveu: > On Sun, 23 May 2010 23:37:29 -0300 > Luiz Americo Pereira Camara wrote: > > >> Mattias Gaertner escreveu: >> [...] >> Here's the actual code (calls a generic TForm descendant): >> >> The article: http://lazarusroad.blogspot.com/ >> > > The article does not explain why the properties must be set before > calling Loaded. > If procedure TMyForm.Loaded; begin inherited; if MyBool then DoAction; end; MyBool will be always false even if called through ShowForm(TMyForm, nil, ['MyBool', True]); From your code it is not clear what you are trying to achieve. From the article also it is not clear. Why are you trying to

do this ? If the property is published, it's value is in the .lfm file, so what is the point of setting it separately ?

Are you trying to use 'custom TForms' with extra properties? In that case it is easier to simply use Lazarus' or Delphi's support for it. I do it every day; I have many thousands of such forms.

Michael.

Reply by email

Luiz Americo Pereira Camara
to Mattias Gaertner: On Mon, 24 May 2010 07:01:21 -0300 Is this correct: One of your forms has a design bug,…
Mattias Gaertner wrote 36 lines
On Mon, 24 May 2010 07:01:21 -0300 Luiz Americo Pereira Camara wrote: > Mattias Gaertner escreveu: > >> On Sun, 23 May 2010 23:37:29 -0300 >> Luiz Americo Pereira Camara wrote: >> >> >> >>> Mattias Gaertner escreveu: >>> [...] >>> Here's the actual code (calls a generic TForm descendant): >>> >>> The article: http://lazarusroad.blogspot.com/ >>> >>> >> The article does not explain why the properties must be set before >> calling Loaded. >> >> >> > If > procedure TMyForm.Loaded; > begin > inherited; > if MyBool then > DoAction; > end; > Is this correct: One of your forms has a design bug, which you can not fix (for whatever reason), so you need a workaround.

It's not intended at a specific case. I just created a way to call generic TForm descendants with generic properties, basically to avoid boilerplate code. It's is already working fine, i'm just trying to avoid an extra notification (the CM_INIT message). I can also use OnShow or CreateWnd. An example:

TEditMyObjectForm = class(TForm)
 [..] //Controls created at design time (stored in the lfm)
published
  //customized property
  property MyObject: TMyObject;
end;

To show that form setting the property MyObject i would do:

Form := TEditMyObjectForm.Create(nil);
try
  Form.MyObject := ObjectX;
  Result :=  Form.ShowModal = mrOk;
finally
  Form.Destroy;
end;

With my function i do:

Result := ShowForm(TEditMyObjectForm, nil, ['MyObject', ObjectX]) = mrOk;
Show quoted text 5 lines
I see several solutions: - Patch and compile your own special version of TReader or LCL. - modify the lfm at runtime - modify the VMT at runtime and override Loaded

Wow. Not necessary too much. I can live with a message handler ;-)

Luiz

Reply by email

Luiz Americo Pereira Camara
to Michael Van Canneyt: do this ? If the property is published, it's value is in the .lfm file, so what is the…
Michael Van Canneyt wrote 36 lines
On Mon, 24 May 2010, Luiz Americo Pereira Camara wrote: > Mattias Gaertner escreveu: >> On Sun, 23 May 2010 23:37:29 -0300 >> Luiz Americo Pereira Camara wrote: >> >> >>> Mattias Gaertner escreveu: >>> [...] >>> Here's the actual code (calls a generic TForm descendant): >>> >>> The article: http://lazarusroad.blogspot.com/ >>> >> >> The article does not explain why the properties must be set before >> calling Loaded. >> > > If > procedure TMyForm.Loaded; > begin > inherited; > if MyBool then > DoAction; > end; > > MyBool will be always false even if called through > > ShowForm(TMyForm, nil, ['MyBool', True]); > From your code it is not clear what you are trying to achieve. > From the article also it is not clear. Why are you trying to do this ? If the property is published, it's value is in the .lfm file, so what is the point of setting it separately ?

See the previous mail. The property is not in the lfm, it's set at runtime.

Are you trying to use 'custom TForms' with extra properties? In that case it is easier to simply use Lazarus' or Delphi's support for it. I do it every day; I have many thousands of such forms.

I'm interested. Can you show me an example?

Luiz

Reply by email

Michael Van Canneyt
to Luiz Americo Pereira Camara
Luiz Americo Pereira Camara wrote 45 lines
Michael Van Canneyt escreveu: > > > On Mon, 24 May 2010, Luiz Americo Pereira Camara wrote: > >> Mattias Gaertner escreveu: >>> On Sun, 23 May 2010 23:37:29 -0300 >>> Luiz Americo Pereira Camara wrote: >>> >>> >>>> Mattias Gaertner escreveu: >>>> [...] >>>> Here's the actual code (calls a generic TForm descendant): >>>> >>>> The article: http://lazarusroad.blogspot.com/ >>>> >>> >>> The article does not explain why the properties must be set before >>> calling Loaded. >>> >> >> If >> procedure TMyForm.Loaded; >> begin >> inherited; >> if MyBool then >> DoAction; >> end; >> >> MyBool will be always false even if called through >> >> ShowForm(TMyForm, nil, ['MyBool', True]); > >> From your code it is not clear what you are trying to achieve. >> From the article also it is not clear. Why are you trying to > do this ? If the property is published, it's value is in the .lfm file, so > what is the point of setting it separately ? See the previous mail. The property is not in the lfm, it's set at runtime. > > Are you trying to use 'custom TForms' with extra properties? In that case > it is easier to simply use Lazarus' or Delphi's > support for it. I do it every day; I have many thousands of such forms. I'm interested. Can you show me an example?

There is an example in lazarus/components/customform.

I also wrote an article on it. If you're interested, I can send it to you tomorrow.

Michael.

Reply by email

Luiz Americo Pereira Camara
to Michael Van Canneyt
Michael Van Canneyt wrote 55 lines
On Mon, 24 May 2010, Luiz Americo Pereira Camara wrote: > Michael Van Canneyt escreveu: >> >> >> On Mon, 24 May 2010, Luiz Americo Pereira Camara wrote: >> >>> Mattias Gaertner escreveu: >>>> On Sun, 23 May 2010 23:37:29 -0300 >>>> Luiz Americo Pereira Camara wrote: >>>> >>>> >>>>> Mattias Gaertner escreveu: >>>>> [...] >>>>> Here's the actual code (calls a generic TForm descendant): >>>>> >>>>> The article: http://lazarusroad.blogspot.com/ >>>>> >>>> >>>> The article does not explain why the properties must be set before >>>> calling Loaded. >>>> >>> >>> If >>> procedure TMyForm.Loaded; >>> begin >>> inherited; >>> if MyBool then >>> DoAction; >>> end; >>> >>> MyBool will be always false even if called through >>> >>> ShowForm(TMyForm, nil, ['MyBool', True]); >> >>> From your code it is not clear what you are trying to achieve. >>> From the article also it is not clear. Why are you trying to >> do this ? If the property is published, it's value is in the .lfm >> file, so what is the point of setting it separately ? > > See the previous mail. The property is not in the lfm, it's set at > runtime. >> >> Are you trying to use 'custom TForms' with extra properties? In that >> case it is easier to simply use Lazarus' or Delphi's >> support for it. I do it every day; I have many thousands of such forms. > > I'm interested. Can you show me an example? There is an example in lazarus/components/customform. I also wrote an article on it. If you're interested, I can send it to you tomorrow.

Please send

Luiz

Reply by email