Merge tabs from child form into main form - delphi

I have page control in main form and page controls in child form , I
place the child form inside the main form by using docking features.
I am not using MDI style
Now both forms have tabs in page control and I need to merge the child form
tabs into the main form page control, what is the best way to do that?

The simplest and best way to handle multiple tabs on a page control is usually with Frames. Take the contents of each tab and factor them out into an individual frame for each tab. Move any shared components, state and code to a data module. Then just place those frames on the tab sheets of your page control.

This is a fairly simple approach that may or may not suit your needs.
For each child tab page you need to merge:
Create a tab in the main form page
control corresponding to the child
tab
Iterate over the Controls in the
child tab and change the Parent
property to the tab page you just
created
You do not need to deal with controls that are children of other controls. e.g. if you have a groupbox in your child tab, then changing it's parent will bring both it and all controls within it to the new parent.
If you need to be able to "unmerge" your tabs at any point then you will need to devise some mechanism to keep track of where the controls came from so you can restore the original Parent as/when needed.
To make things slightly easier you could place a TPanel in the child tabs, with it's Align property set to alClient. Place all the controls in the tab on that panel and then when you need to merge/unmerge you need only set the Parent of the panel control.

I just tried
procedure TForm1.Button1Click(Sender: TObject);
begin
while Form2.PageControl1.PageCount > 0 do
Form2.PageControl1.Pages[0].PageControl := PageControl1;
end;
and it worked fine. Am I missing something obvious, or why is everybody giving such sophisticated solutions? :-)

Related

Parent components show over child form

I've been following the below page in order to have a child Form that I can click on its components (such as an edit) and have proper focus:
Working with MDI Forms in Delphi
The problem now is that the components on the parent Form show on top of the child Form. If I use the SendToBack() command for those components, they completely disappear. Here is a screenshot of what happens:
EDIT:
I have a Form with buttons and a ListView that displays client info. When I click on a client, I can click a button to view or edit that client, alternatively add a new one. The Edit/Add pops up a Form where I can input the info and save it. I'm using an OnClick event for each Edit that has a SetFocus(). That gets focus on each Edit, but then all the text is selected, so I cannot click on the line and start editing text - it just overrides unless I use an arrow first.
Initially, I used regular Forms and that's where I had the focus issue. MDI fixed that, but now it's the parent components that show on top of the child.
Concerning MDI forms: that is how MDI works. The main form is not supposed to have anything else than a menu bar and optionally a toolbar, aligned alTop. The child forms use the rest of the space. Well as #RemyLebeau suggested, you can add other controls too, if you align them.
But it turned out that the actual problem with using ordinary secondary forms was that the text in an edit control on the secondary form becomes selected when you set focus to the edit control in a button click. That is easy to change, right after you set the focus to an edit control:
Edit2.SelLength := 0; // nothing selected, cursor at beginning
Edit3.SelStart := Length(Edit3.Text); // nothing selected, cursor at end of text

Tabbed control for Delphi?

I'm using Delphi XE8.
I want to create a tabbed control, with each tab having its own panel. I tried TTabControl, for which I can create different tabs. But when I drop a component on the control with the first tab active, it remains visible when I change the tab (TabIndex). How can I in design time create different layouts for the different tabs? Or am I using the wrong component?
You are using the wrong component. You need to use TPageControl. Each page of a page control has its own distinct set of controls. From the documentation:
TPageControl is a set of pages used to make a multiple page dialog
box.
Use TPageControl to create a multiple page dialog or tabbed notebook.
TPageControl displays multiple overlapping pages that are TTabSheet
objects. The user selects a page by clicking the page's tab that
appears at the top of the control. To add a new page to a TPageControl
object at design time, right-click the TPageControl object and choose
New Page.
To create a tabbed control that uses only a single body portion
(page), use TTabControl instead.

embedding a FMX forms

There is some code regarding embedding a FMX form into a panel...
http://docwiki.embarcadero.com/CodeExamples/XE5/en/FMXEmbeddedForm_(Delphi)
....I want to embed multiple forms into the same panel, closing the prior
one of course. I'm having an issue with the proper to close./free those
forms when using the method to embed them from that docwiki.
from testing I have found that the form is not actually embedded but that the objects on the form are moved onto a new parent simulating the effects of an embedded form.
In the vcl this was pretty easy to do but in dmx it's a different ball game.
Any thoughts?
The easiest method to do this is to put a transparent layout on each form as top level component.
When you need to embed a form in your panel, just create an instance of your form and change the parent of it's layout to your panel.
When you don't need the embedded form, you can reparent the layout to its form and free it.
When you embed a form you are, as you state, reparenting some of the components from the embedded form onto the containing form.
If you want to remove those components you can either:
reparent them to something other than the containing form (e.g. back to their original form). Do this if you have multiple forms which you want to be able to swap in and out without having to destroy and recreate all the time.
Free the embedded form (use DisposeOf under ARC). This will both destroy the form and it's controls and remove them from the containing form. (Note that while the containing form becomes the Parent, the original, embedded form stays as the Owner. This the controls are destroyed when the embedded form is destroyed.
You can then create and reparent another form in it's place.
Also note that you can safely embed multiple forms onto one container form but you will need to use a different object as a container for each one. You can also put multiple components or sets of components onto an embeddable form and embed them into separate locations on a container form or even onto multiple forms.
However you can only embed each control(s) into one form at a time.

Delphi - child forms have frame of parent

I have a delphi application with multiple forms. Initially I had tried a setup where each newly opened form was a frame and the "parent" of this form (whichever called to open the form) was hidden as the child was shown with the child being resized and relocated to give a seamless effect of having one window, when the child is closed the parent is relocated and again made visible. All forms have a bsSingle border style for the Windows title block.
This approach worked well for positioning however the issue I have is a noticeable flicker as the parent form is closed and the child opened, and as there is a small time period where no form is opened the icon/tray on the start bar would shift around and itself become hidden and visible.
Does anybody have any advice on solving this problem? I thought perhaps if I only had one form with the border within the application and opened each new form within this border it would work better - though I am unsure how exactly to do this.
Any help is much appreciated.
It is easy to make one form appear as a child inside another. Create a new form which will contain and create your other forms:
procedure TMainForm.FormCreate(Sender: TObject);
var
F : TForm;
begin
F := TOneOfYourChildForms.Create(Self);
F.Parent := Self;
F.Show();
end;
Create both your child forms similar to this, then just do Show on the one you want to display and Hide on the other. Set BorderStyle to bsNone on the child forms to remove the caption. Turn off Auto-Create on your forms in project settings if you create them yourself like this instead.
I've had success with this design, and I think it helped to have the contents of the "main form" within a TFrame as well. When you want to show the main form, you would just perform a frame swap.

form main + form child stacking issue

I am using main form and child forms.
If I open 2nd child form with
TMYForm.Create(nil);
It does not stack it on the 1st child form top.
Is there any way for 2nd and X'th child form to appear in exact same position as 1st child form?
Or I need to destroy old child form while creating new one (as stacking is done automatically)?
That is the expected behavior. Without specifying otherwise, Forms will open on the right and down from the position of the previously opened.
If you want to control the position of your form, change its Position property to poDesigned, but you have to set its Top and Left properties to ensure it'll be visible.
Or you can used some presets: poDesktopCenter, poMainFormCenter, poOwnerFormCenter or poScreenCenter.
Try putting this:
TMYForm.Position:=poMainFormCenter;
or
TMYForm.Position:=poOwnerFormCenter;
Before TMYForm.Create(nil);
-S
If you have references to the child forms, use Form2.BoundsRect := Form1.BoundsRect

Resources