Jump to content
Stano

TFrame versus SubForm

Recommended Posts

HI,

when I tried TFrame more than 20 years ago, I had problems. I was immediately recommended to use SubForm. At that time TFrame was very unreliable.
The question is: has that changed? Is TFrame problem free?

Share this post


Link to post

Are SubForms problem free?

 

It boils down to what your are trying to achieve.

 

Recently I developed a VCL  application for a customer that is almost solely build on frames. You need forms for dialogs and tool windows, but even those are just containing a frame. 

 

The IDE itself is built on frames, too. (OK, that may not really count for problem free)

  • Haha 1

Share this post


Link to post
1 hour ago, Stano said:

Is TFrame problem free?

The biggest problem is when you create descendant forms (i.e. at design-time) where the ancestor contains frames. Otherwise, for me they're totally fine.

  • Like 1

Share this post


Link to post

Can you shed some light on what a "SubForm" is? I am working with frames all the time.

 

The IDE will show the wrong frames and throw error messages if you are opening project groups where the name of a frame class is not unique throughout all projects in that group.

 

The IDE will often randomly redundantly copy parts of a frame on its container's .dfm file (even entire image lists). You will have to use your versioning system and watch carefully to commit only the parts you changed yourself, and not the random insertions by the IDE.

  • Like 1

Share this post


Link to post
6 hours ago, Dave Nottage said:

The biggest problem is when you create descendant forms (i.e. at design-time) where the ancestor contains frames. Otherwise, for me they're totally fine.

Yes I totally agree I'm using frames in my projects sometimes in descendant forms and this is the biggest problem I have encountered. Especially in managing events on descendant frame components that often become disconnected. At some point I started managing and connecting them at runtime.

  • Like 1

Share this post


Link to post

We use a lot of frames, but we almost always instantiate, reparent and connect them at runtime.  Usually, we have a panel as a "host" for the frame, which lets the panel deal with the in-form alignment, so that the frame can use alClient.
As @Davide Angeli mentions, loss of events has been a key factor for deciding to do it that way.

  • Like 2

Share this post


Link to post
8 hours ago, Uwe Raabe said:

Are SubForms problem free?

Yes.

I asked the question mainly out of curiosity. Thank you for all the answers

1 hour ago, Der schöne Günther said:

Can you shed some light on what a "SubForm" is?

I create a form and set its Parent to some component on the "base" form.
I don't have any problems with this.

Share this post


Link to post
2 hours ago, Stano said:

I create a form and set its Parent to some component on the "base" form.
I don't have any problems with this.

That is almost the same as @Lars Fosdal describes:

2 hours ago, Lars Fosdal said:

We use a lot of frames, but we almost always instantiate, reparent and connect them at runtime.

This approach indeed eliminates the mentioned problems that may come up when placing the frames at design time.

Share this post


Link to post

Another benefit is that we usually wait with initializing the frames until they are actually used.

Saves init time on app startup.

Share this post


Link to post

I use frames as complex, visual UI much like a component without creating a real IDE custom component.
While it still has the advantage of visual design.

I use mainly FMX, but that should work same under VCL too, by using an interposer class of TFrame, for easy management.
At runtime I add them to a special "carrier" in the parent form or frame, which can be TRectangle, TLayout or other.

So this is not a drag-and-drop approach, but the runtime approach works very well and gives a lot of flexibility and stability.

Share this post


Link to post

Hi!

 

For me the biggest problem is when you need to add some additional "TEdit" in a frame in a certain scenario.

 

I think that with "SubForms" you don't have that problem.

Share this post


Link to post

Can you explain how you come to this conclusion?

 

Adding a TEdit to a frame is no different from adding a TEdit to a form.

 

Basically a "SubForm" is just a TForm descendant, which Parent is set to another control at runtime. During design time the "SubForm" is designed as any other form. So is a frame.

 

I guess, you are referring to adding a TEdit to a frame during design time while it is inlined (placed) into another form. You have to switch to the frame designer to do that and switch back to the form to see the change in the form.

You also need to switch to the form designer of a "SubForm" to do that. In contrast to the inlined frame you can see the actual outcome at runtime only.

 

 

Share this post


Link to post

The one difference that I encounter is that a "SubForm" is not linked to anything at design-time. If you have placed a TFrame anywhere in the project, the frame is now linked and "in use" by the designer.

 

I often encounter "has open descendents [sic] or linked modules. Cannot close." dialogs when trying to modify a frame, TDataModule descendant, or a base form (when using form inheritance). This often happens when I try to switch between form designer and DFM text editing. I can close every unit that the editor/designer has open, re-open the "linked" unit, and still can't switch to text DFM. At that point, I could just edit the DFM in my favorite text editor, except Delphi will not reload the DFM once my edits are finished. So I typically restart the IDE.

 

I still use D7 occasionally. While this does happen in D7, and I remember it in D6, there seem to be more scenarios where D11 refuses to switch and D7 doesn't.

Share this post


Link to post
48 minutes ago, JonRobertson said:

The one difference that I encounter is that a "SubForm" is not linked to anything at design-time. If you have placed a TFrame anywhere in the project, the frame is now linked and "in use" by the designer.

This is interesting information regarding Frame. It's probably worth the effort to study it.

Share this post


Link to post
1 hour ago, JonRobertson said:

The one difference that I encounter is that a "SubForm" is not linked to anything at design-time. If you have placed a TFrame anywhere in the project, the frame is now linked and "in use" by the designer.

Indeed - and it is just because you simply cannot place a "SubForm" anywhere at design time. If you don't do it with a frame both are on par again.

Share this post


Link to post

I use practically 90% of TFrame and 10% of TForm.
IDE sometimes is wrong to place or list the available TFrame so I add them programmatically.
No issue in this way.

Share this post


Link to post

So what I gather from this thread is

  1. The IDE supports placing frames at design time. While that enables sharing or referencing components like ImageLists, it may come with additional challenges (and bugs)
  2. The VCL both supports placing and re-parenting frames and forms at runtime. There is virtually no difference between these two

Correct?

 

Share this post


Link to post

I've never tried working with subforms, so I can't say much about that.

Share this post


Link to post

I wonder how subforms work under High-DPI conditions. There are several places in this area where a TForm is acting different to a TFrame.

Share this post


Link to post
Posted (edited)
2 hours ago, Lars Fosdal said:

I've never tried working with subforms, so I can't say much about that.

It worked for me too, but placing a SubForm on a main form turns out to assign (copy) all components parents from the SubForm to the main form.

I use carrier components (TLayout, TPanel, ...) here too, so to be able to assign a SubForm-Carrier parent to a carrier component in the MainForm.

Perhaps there are different methods to achive that too, but I found this was the only reliable solution at that time.
 

Edited by Rollo62

Share this post


Link to post
1 hour ago, Uwe Raabe said:

I wonder how subforms work under High-DPI conditions. There are several places in this area where a TForm is acting different to a TFrame.

 

I don't know what the IDE uses, but it is not usable on a mixed DPI multi monitor systems. I was forced to debug an aplication in such a scenario. Both the application and the IDE failed.

Share this post


Link to post
3 hours ago, Lajos Juhász said:

 

I don't know what the IDE uses, but it is not usable on a mixed DPI multi monitor systems. I was forced to debug an aplication in such a scenario. Both the application and the IDE failed.

My laptop's "recommended" scaling is 125%. At the office, I have two external monitors, each has recommended scaling of 150%.

 

I started this position eight months ago. The first project that I worked on uses a "tabbed interface", similar to web browsers, where each form is created and parented to a TTabSheet. Nothing more than setting frmSomeForm.Parent := tsSomeForm. Every form, except a few "dialog box" forms, are embedded in the app's main form.

 

Two of the forms in that application also contain a TFrame, which is on the form at design-time rather than created and attached at run-time.

 

I have not seen any DPI related issues since switching to DPI Unaware mode when launching BDS.

Share this post


Link to post
4 hours ago, Rollo62 said:

It worked for me too, but placing a SubForm on a main form turns out to assign (copy) all components parents from the SubForm to the main form.

I don't agree with this.

          frmView := TfrmView.Create(Self);
          frmView.Parent := tsView;

This makes the tabsheet the parent of the form. So now all controls on the form have the tabsheet as a grandparent, if you will. But the parent of each control on the subform is not changed to the tabsheet.

Share this post


Link to post
6 hours ago, Der schöne Günther said:

The IDE supports placing frames at design time. While that enables sharing or referencing components like ImageLists

Not sharing components, or sharing a single instance of a component. If a frame contains an ImageList and is used on multiple forms, each form creates a separate instance of the frame and all components on the frame. So you have multiple copies of the same ImageList, but those forms are not "sharing" the ImageList.

 

I use a TDataModule for resources and components, such as TImageCollection and TVirtualImageList, that are used by multiple forms.

Share this post


Link to post
50 minutes ago, JonRobertson said:

I use a TDataModule for resources and components, such as TImageCollection and TVirtualImageList, that are used by multiple forms.

Using the same TVirtualImageList for several forms will fail if these forms are placed on monitors with different DPI. One of the main tasks of TVirtualImageList is to adjust the size of its images to match the DPI of the form. To achieve this they have to be owned by the form. See TVirtualImageList.DPIChangedMessageHandler.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×