Is there a way to show MDI child forms (FormStyle = fsMDIChild) on the main form that has a frame with Align = alClient?
Creating a frame on the main form:
Frame := TfrCalendar.Create(Self);
Frame.Parent := Self;
Creating MDI child form on the main form:
if Assigned(FMDIRef)
then
FMDIRef.BringToFront
else begin
FMDIRef := TFReference.Create(Application);
FMDIRef.Show;
end;
After this, the child form is not visible. If you do not create a frame, the form is visible. If you first show the child form, and then create a frame on the main form, then the child form becomes invisible again.
The issue here is that your frame is competing for space with the MDI client window. The MDI client window is the window which is parent to the MDI child windows.
In your scenario the frame consumes all remaining client area inside the main window, thus leaving no space for the MDI client window.
What you are attempting is not possible. The MDI client window has to go somewhere, and you must leave it some room.
Depending on what your actual goal is, different solutions are available:
If the frame is intended to be visible always, then use alTop. The remaining space below it will be available to the MDI client window.
If you wish to show an image on the MDI client window to act as a background, refer to my answer here: https://stackoverflow.com/a/15137740/505088
Related
Based in this my working code, now i need of a ScrollBox component and a Image component inside he. Eg:
The problem now is the ScrollBox. The MDIChild Form always stays behind, you can test, changing ScrollBox Align (None/Client) property.
Then what is need to MDIChild Form stay above of ScrollBox?
The MDI client window that hosts the MDI child forms is the bottom most window of the MDIForm's content. You can't make MDI child forms appear on top of anything else, because literally everything else placed on the MDIForm is on top of the MDI client window and thus on top of the child forms.
I have a parent and child form in Delphi. Parent form contains a TControlBar and on the top of ControlBar there are two Toolbars.
On one of the toolbars there is a button which is used to open the child form.
When child form is displayed, top partion of the form goes below the control bar and top portion of the child form goes hidden below the parent form.
I think the problem is that my child form is using full part of the parent form as the display area.
To my knowledge, I think child form should use ClientWidth and ClientHeight as the display area.
ClientWidth and Clientheight is automatically set.
I want child form to use the remaining area (other then toolbar) for display purpose.
MDI child windows are children of the MDI client window, that's the window that you refer to as the 'remaining area'. Hence they cannot go above any other window parented by the form, like controlbars, toolbars, panels etc.. Additionally, MDI child windows are not constraint with the size of this MDI client window, you can think of the MDI client as an auto-scroll window. Child windows can be moved to overrun any of the edges and a scroll bar will appear to make it possible to restore a full view on them.
If I understand correctly what you want to do, you have to maximize the child windows. You can set the WindowState property of child windows to wsMaximized to that effect.
There is the good component to maximize a child window in a client area (the SHIFT key must be held) - NLDExtraMDIProps.
Or this code can be used:
procedure WMSIZE(var Msg: TMessage); message WM_SIZE;
procedure TForm2.WMSIZE(var Msg: TMessage);
begin
inherited;
if Msg.WParam = SIZE_MAXIMIZED then
begin
ShowWindow(Handle, SW_RESTORE);
Left := 0;
Top := 0;
Width := Form1.ClientWidth - 4; // The BORDER
Height := Form1.ClientHeight - 4;
end;
end;
But maximizing isn't real maximizing. The child window is only aligned to the client area. It must automatically resize and fit the client area when the parent window is resized, the maximize/restore system button must change etc.
I try to accomplish effects that are described below.
As you see on the pictures the child windows are maximized, and
they don't take the entire parent window (only the client area).
It's impossible to move them over the caption/title bar because they are maximized.
They have the restore button, not the maximize button any more.
They are aligned to the client area (resizing of the parent window causes resizing of the child one withing the client area).
The code in my question and the component don't do like the child windows on the pictures.
Can we make a window really maximized (not just aligned)?
Not maximized (not good; the component and the code from my question maximize like on these pictures):
Maximized (what I need):
I do not understand your problem. Maximizing an MDI child window is done:
programmatically: by using ShowWindow(ActiveMDIChild.Handle, SW_MAXIMIZE),
manually: by clicking the Maximize border icon, or by double clicking on the form caption.
Both these actions result in:
the disappearance of the child window border (collapses into the MDI form border),
the addition of small border icons (for the child window) to the main menu bar,
a resize effect similar to that of Align=alClient.
To restrict the available space for the child windows within the main form, make sure to align windowed controls to edges of the form.
Setting the Align or Anchors properties for MDI child windows has no effect: they are not part of the default VCL aligning implementation anymore; Windows has taken over that job.
If you want to intervene on the resizing of an MDI child, then handling WM_SIZE is the wrong approach, because that message is send áfter the resize. Instead, handle WM_SYSCOMMAND as I explained here.
As for my component that you refer to:
Manually maximizing by clicking the Maximize border icon does exactly thát: a default maximize operation as outlined above,
Manually maximizing by clicking the Maximize border icon - while holding the Shift key - does resize the child window to the largest spare space within the MDI form. In this case, resizing the MDI main form does nót resize the MDI child forms.
if (Msg.WParam = SIZE_MAXIMIZED) then
begin
Left := 0;
Top := 0;
Width := frmMain.ClientWidth - 4;
Height := frmMain.ClientHeight - 4;
SendMessage(Handle, WM_SIZE, SIZE_RESTORED, 0);
end;
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.
Is it possible to show a modeless "wsNormal" WindowsState form behind a MDIChild form? I want to create a NOTE form which is always behind other forms (but always in front of the MDI form), unless you bring it to the front. E.g when you click on it.
That's technically impossible for window that is not an child of the MDI container.
The MDI children are child windows of the MDI container which is a child of the main form. If a window is in front of the main form, then it is in front of the MDI children. If it is behind the main form, then it is behind the MDI children.
Normally no, MDI parent is the root parent of MDI childs, you're either below the MDI parent or above. But you can set the parent of your top-level form to be the MDICLIENT.
I wouldn't suggest this approach as it possibly would have complications (maybe(?) you can achieve the same effect by tweaking some other MDI client class). But if you want to try what it would look like create a new "MDI Application" project and change the code that runs from the Help->About menu item to:
procedure TMainForm.HelpAbout1Execute(Sender: TObject);
begin
// AboutBox.ShowModal;
windows.SetParent(AboutBox.Handle, ClientHandle);
AboutBox.Show;
SetWindowPos(AboutBox.Handle, HWND_BOTTOM, 0, 0, 0, 0,
SWP_NOSIZE or SWP_NOMOVE);
end;