Sign in Join

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

Mailing lists / lazarus / 2011-02

A change in LCL require your TCustomForm descendants to have a resource or to use a CreateNew constructor

14 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

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

Paul Ishenin

Hello, Lazarus mailing list.

I've changed the behavior of TCustomForm.Create constructor. Now it raises an exception if your TCustomForm descendant has no resource.

1. Why the change is needed.

Historically TCustomForm has 2 constructors: Create() - for creating forms from resources and CreateNew() - for resourceless forms. When IDE creates a new form it creates a new unit (.pas file) and a new resource (.lfm file). IDE also adds {$R *.lfm} directive into the form unit file to attach the form resource into the executable. During the runtime TCustomForm.Create searches for resource and construct itself based on information from that resource. But what can happen if it can't find an appopriate resource? You will see an empty form. I think most of you will spend plenty of time trying to understand why do you see an empty form if you or someone else accidentally remove the {$R *.lfm} directive. So absence of the form resource is an exceptional situation and LCL must report an exception. LCL already report an exception if you have no resource for TFrame and TDataModule descendants.

On the other hand there are some situations when you want to construct a form in code without any resources. How to be in this case? You must use CreateNew() constructor - the difference between Create and CreateNew only in resource search. Moreover Create constructor also calls CreateNew inside.

2. How this change can affect your applications.

This change is applied only for new projects created by the Lazarus IDE. It does not affect your old projects.

3. Should you change anything in your application.

Yes, please do. If you are using Create() constructor to construct your resourceless forms - you are doing a mistake. Please replace it with CreateNew(). This will also speedup your form construction because no resource will be searched and no resource will be accidentally loaded. To simplify the search of accidental Create() constructor calls set "RequireDerivedFormResource" variable to True and test how your application works. If you see no exceptions - then you are doing things right.

4. How to change the behavior back.

The behavior is controlled by a global variable
*RequireDerivedFormResource* which is set to True for all new applications created by the IDE and is set to False by default. If you for some reason want the old behavior just remove
"RequireDerivedFormResource := True" line from .lpr file of your new application.

Best regards, Paul Ishenin.

Reply by email

Zaher Dirkey
to Paul Ishenin: Hello, Lazarus mailing list. I've changed the behavior of TCustomForm.Create constructor.…
Paul Ishenin wrote
RequireDerivedFormResource := True

Thanks, i fall with this mistakes before.

But i like to be RequireDerivedFormResource := True by default, for old
projects it must add RequireDerivedFormResource := False, that reduce the
lines in the new projects lpr files and more safe for old projects that no
need to create resourceless forms.
Zaher Dirkey -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110202/19d0e4e6/attachment.html>

Reply by email

Vincent Snijders
to Zaher Dirkey

2011/2/2 Zaher Dirkey :

But i like to be RequireDerivedFormResource := True by default, for old

I would like that too.

projects it must add RequireDerivedFormResource := False, that reduce the lines in the new projects lpr files and more safe for old projects that no need to create resourceless forms.

But it is very hard (imposisble) to change an old project automatically.

Vincent

Reply by email

Unknown author
to Paul Ishenin: Hello, Lazarus mailing list. I've changed the behavior of TCustomForm.Create constructor.…
Paul Ishenin wrote 11 lines
Hello, Lazarus mailing list. I've changed the behavior of TCustomForm.Create constructor. Now it raises an exception if your TCustomForm descendant has no resource. The behavior is controlled by a global variable *RequireDerivedFormResource* which is set to True for all new applications created by the IDE and is set to False by default. If you for some reason want the old behavior just remove "RequireDerivedFormResource := True" line from .lpr file of your new application.

I think you should do the opposite: The default should be 'True', and users should disable this explicitly. That would also be Delphi compatible.

There is one caveat: The TForm class itself should not search for a resource, only TForm Descendants should do this.

Michael.

Reply by email

Paul Ishenin
to Unknown author
I think you should do the opposite: The default should be 'True', and users should disable this explicitly. That would also be Delphi compatible.

Michael, I though you are reading the developers list. The default False value has come to protect old projects.

There is one caveat: The TForm class itself should not search for a resource, only TForm Descendants should do this.

Yes, it is so now.

Best regards,
Paul Ishenin

Reply by email

Unknown author
to Paul Ishenin
Paul Ishenin wrote 6 lines
02.02.2011 17:49, wrote: > I think you should do the opposite: The default should be 'True', and users > should disable this explicitly. That would also be Delphi compatible. > Michael, I though you are reading the developers list. The default False value has come to protect old projects.

I am not on the Lazarus developer list...

> There is one caveat: The TForm class itself should not search for a > resource, only TForm Descendants should do this. Yes, it is so now.

Great :-)

Michael.

Reply by email

Bart
to Unknown author: I think you should do the opposite: The default should be 'True', and users should…

What is the meaning of the second parameter in CreateNew()? I cannot see it being used in TCustomForm.CreateNew().

Bart

Show quoted text 35 lines
On Wed, 2 Feb 2011, Paul Ishenin wrote: > Hello, Lazarus mailing list. > > I've changed the behavior of TCustomForm.Create constructor. Now it raises > an > exception if your TCustomForm descendant has no resource. > > > The behavior is controlled by a global variable > *RequireDerivedFormResource* > which is set to True for all new applications created by the IDE and is > set > to False by default. If you for some reason want the old behavior just > remove > "RequireDerivedFormResource := True" line from .lpr file of your new > application. I think you should do the opposite: The default should be 'True', and users should disable this explicitly. That would also be Delphi compatible. There is one caveat: The TForm class itself should not search for a resource, only TForm Descendants should do this. Michael. -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Paul Ishenin
to Bart
Bart wrote
What is the meaning of the second parameter in CreateNew()? I cannot see it being used in TCustomForm.CreateNew().

Search the google. Something for c++ builder as I remember.

Best regards,
Paul Ishenin

Reply by email

Mattias Gaertner
to Unknown author: I think you should do the opposite: The default should be 'True', and users should…

?
?

hat am 2. Februar 2011 um 11:49 geschrieben:

Show quoted text 20 lines
On Wed, 2 Feb 2011, Paul Ishenin wrote: > Hello, Lazarus mailing list. > > I've changed the behavior of TCustomForm.Create constructor. Now it raises > an > exception if your TCustomForm descendant has no resource. > > > The behavior is controlled by a global variable *RequireDerivedFormResource* > which is set to True for all new applications created by the IDE and is set > to False by default. If you for some reason want the old behavior just > remove > "RequireDerivedFormResource := True" line from .lpr file of your new > application. I think you should do the opposite: The default should be 'True', and users should disable this explicitly.?

This would break existing projects without need.
?
?

That would also be Delphi compatible.?

That's why it is enabled for new projects. Don't forget this is just a warning that something might be missing. It is not a necessary bug fix. ?
?

There is one caveat: The TForm class itself should not search for a resource, only TForm Descendants should do this.

Huh?
That was always so.

Mattias
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110202/b7cd2bbb/attachment.html>

Reply by email

Unknown author
to Mattias Gaertner
Mattias Gaertner wrote 26 lines
? ? hat am 2. Februar 2011 um 11:49 geschrieben: > > > On Wed, 2 Feb 2011, Paul Ishenin wrote: > >> Hello, Lazarus mailing list. >> >> I've changed the behavior of TCustomForm.Create constructor. Now it raises >> an >> exception if your TCustomForm descendant has no resource. >> >> >> The behavior is controlled by a global variable *RequireDerivedFormResource* >> which is set to True for all new applications created by the IDE and is set >> to False by default. If you for some reason want the old behavior just >> remove >> "RequireDerivedFormResource := True" line from .lpr file of your new >> application. > > I think you should do the opposite: The default should be 'True', and users > should disable this explicitly.? This would break existing projects without need.

I did some tests. For a TDatamodule descendant, TMyDataModule.Create(Nil) gives an error if there is no resource. For a form, the form remains empty.

I knew about the former, and had assumed the form would react the same as TDataModule.

It does not, apparently.

> That would also be Delphi compatible.? That's why it is enabled for new projects. Don't forget this is just a warning that something might be missing. It is not a necessary bug fix.

Indeed.

> There is one caveat: The TForm class itself should not search for a resource, > only TForm Descendants should do this. Huh? That was always so.

I was just remarking on the possibility, in case it was missed.

Michael.

Reply by email

Mattias Gaertner
to Unknown author

?
?

hat am 2. Februar 2011 um 15:48 geschrieben:

Show quoted text 7 lines
[...] >> I think you should do the opposite: The default should be 'True', and users >> should disable this explicitly.? > This would break existing projects without need. I did some tests. For a TDatamodule descendant, TMyDataModule.Create(Nil) gives an error if there is no resource. For a form, the form remains empty.?

A TDataModule without resource makes no sense. At runtime instead of a TDataModule you can use any TComponent.
Same for TFrame. At runtime you can use a TPanel instead. That's why it makes sense to raise an exception if a TFrame/TDataModule is created without a resource.
OTOH a form without resource makes sense and is often done.

?

?

I knew about the former, and had assumed the form would react the same as TDataModule.?

There are more differences than similarities between TForm and TDataModule. And TForm is older than TDataModule.
?

Mattias
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110202/4ba0d015/attachment.html>

Reply by email

Vincent Snijders
to Paul Ishenin: Hello, Lazarus mailing list. I've changed the behavior of TCustomForm.Create constructor.…

2011/2/2 Paul Ishenin :

Show quoted text 48 lines
Hello, Lazarus mailing list. I've changed the behavior of TCustomForm.Create constructor. Now it raises an exception if your TCustomForm descendant has no resource. 1. Why the change is needed. Historically TCustomForm has 2 constructors: Create() - for creating forms from resources and CreateNew() - for resourceless forms. When IDE creates a new form it creates a new unit (.pas file) and a new resource (.lfm file). IDE also adds {$R *.lfm} directive into the form unit file to attach the form resource into the executable. During the runtime TCustomForm.Create searches for resource and construct itself based on information from that resource. But what can happen if it can't find an appopriate resource? You will see an empty form. I think most of you will spend plenty of time trying to understand why do you see an empty form if you or someone else accidentally remove the {$R *.lfm} directive. So absence of the form resource is an exceptional situation and LCL must report an exception. LCL already report an exception if you have no resource for TFrame and TDataModule descendants. On the other hand there are some situations when you want to construct a form in code without any resources. How to be in this case? You must use CreateNew() constructor - the difference between Create and CreateNew only in resource search. Moreover Create constructor also calls CreateNew inside. 2. How this change can affect your applications. This change is applied only for new projects created by the Lazarus IDE. It does not affect your old projects. 3. Should you change anything in your application. Yes, please do. If you are using Create() constructor to construct your resourceless forms - you are doing a mistake. Please replace it with CreateNew(). This will also speedup your form construction because no resource will be searched and no resource will be accidentally loaded. To simplify the search of accidental Create() constructor calls set "RequireDerivedFormResource" variable to True and test how your application works. If you see no exceptions - then you are doing things right. 4. How to change the behavior back. The behavior is controlled by a global variable *RequireDerivedFormResource* which is set to True for all new applications created by the IDE and is set to False by default. If you for some reason want the old behavior just remove "RequireDerivedFormResource := True" line from .lpr file of your new application.

What about adding TApplication.CreateNewFrom?:
http://bugs.freepascal.org/bug_view_advanced_page.php?bug_id=19678

Is that a necessary extension?

Vincent

Reply by email