I was wondering why Delphi (2007) provides three widgets that seem to do the same thing, and what the advantages/disadvantages are for each.
On the same topic, if I want to display different sets of controls, why should I favor eg. PageControl + TabSheets + Frames, instead of just displaying different frames directly on the parent form?
Thank you.
From the helpfile on TTabSet:
Tab set controls are commonly used to display tabbed pages within a dialog box. TTabSet is provided for backward compatibility. Use TTabControl component in 32-bit Windows applications.
So the real question is, what's the difference between TTabControl and TPageControl? The difference is that TTabControl only has one "page", whereas TPageControl has one page for each tab. This makes them useful in different situations.
TPageControl is useful for dialogs where you want to fit more UI on the screen than you have screen space to fit it in. Organize your UI into categories and put each category on one page. You see this pattern a lot in Options dialogs, for example.
TTabControl, on the other hand, works well for working on an array/list of objects. Create a UI to display and edit the properties of a single object, and place it on a TTabControl, then create one tab for each object and set up the event handlers so it'll load a new object from the array into the controls whenever you change tabs.
As for the frames question, the main reason to use a TPageControl in conjunction with frames is because it provides a prebuilt way to decide which frame to display. That way you don't have to reinvent a mechanism for it.
One method that I have used with great success is to use frames with a TPageControl and late bind my frames to the tPageControl the first time the page is selected. This keeps the form load time down, by not creating frames which are never viewed, but yet allows the flexibility of being created, the state is maintained when changing between tabs. Recently I switched to using forms and embedding them instead of frames...but the concept is the same.
The same can be done using a single "mount point" on a TTabControl and switching it out as the tab is changed, but then the issue of how to deal with the tab state as tabs are switched back too comes up.
[EDIT] The question comes up how do I handle communication between the frame and the parent form. This actually is very easy to do using interfaces. Just create a new unit that will be shared by the form AND the frame and add two interfaces:
type
IFormInterface = interface
[guid]
procedure FormProc;
end;
IFrameInterface = interface
[guid]
procedure SetFormController(Intf:IFormInterface);
end;
Have the form implement the IFormInterface, and the frame implement the IFrameInterface. When you click on a tab and show a frame, then run code like the following:
var
FrameIntf : IFrameInterface;
begin
if Supports(FrameObj,IFrameINterface,FrameIntf) then
FrameIntf.SetFormController(Self);
end;
your frame implementation of the SetFormController method would then hold onto the reference passed, which would allow it to call upwards into the form.
procedure TFrame1.SetFormController(Intf:IFormInterface);
begin
fFormController := Intf;
end;
Procedure TFrame1.Destroy; override;
begin
fFormController := nil; // release the reference
inherited;
end;
Procedure TFrame1.Button1Click(Sender:tObject);
begin
if fFormController <> nil then
fFormController.FormProc
else
Raise Exception.Create('Form controller not set');
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With