MDI interface with FireMonkey - delphi

Is it possible to create an MDI application using FireMonkey in a traditional sense of many documents forms/frames and one master form?
I'm specifically interested since there are no MDI controls on forms anymore.. Has it been replaced with something different?
EDIT: Adding to the question, when I create child forms they all showed separately in taskbar, even the OpenDialogs..

Here's one approach you can use:
1) Create your individual forms as normal, except use a TLayout, call it "LayoutMain", (aligned alClient) as the parent of all controls on that form.
2) On your "master form", when you want to bring a form instance in to behave as it would as an MDI interface, create a TLayout (call it "FormContainer" or something), place as a child of that (aligned to top) another TLayout (call it "FormHeader"), containing the individual controls for the Form Caption, the Minimize/Maximize/Close buttons and anything else you'd like on the "frame" heading. This is called a Composite.
3) Create an instance of your child form (but don't show it), then parent that instance's primary TLayout "LayoutMain" to your main form's TLayout "FormContainer".
4) On the TLayout previously mentioned (with the name "FormHeader"), give it OnMouseDown and OnMouseMove events to provide the ability to drag it around the Master Form.
When you want to maximize the child form inside the master form, you'd just set the outer TLayout "FormContainer" align property to alClient, remembering to store its original Top, Left, Width and Height values within the the form's instance so you can recall them when pressing the Restore button.
True, this is a fairly involved solution, but to the very best of my knowledge this is the only way you're going to achieve what you're trying to do with FireMonkey as it exists today (circa Update 2).
I wouldn't expect Embarcadero to provide any form of MDI emulation as part of FireMonkey "out of the box", as MDI is considered an old-fashioned approach.
The more modern solution would be to use Docking, as the RAD Studio IDE itself does. This provides the very best of both worlds, giving the user the freedom to choose what child forms they want to link into the master form, or display outside of that on their own (or any combination of docked arrangements).

Related

Is there a way to implement a bottom-up event notification in Firemonkey?

I have a container control (TLayout or TPanel or TScrollbox, etc.) which can have several other nested controls inside. Is there a way in Firemonkey to know when the container becomes "active"? I mean for example:
when any of its children get focus or
user clicks any of its non-focus controls
I am asking for a kind of event-bubble. OnClick would be enough so when user clicks any nested control, the parent container is notified. Control's HitTest property would be a solution but if I set that property to False (to let the parent manages the onlick) on a TEdit, it becomes useless obviously (I can't type on it)
Edit:
A simple layout example:
Drop a TScrollBox in a form
Drop a TPanel in form and put it as child of the TScrollBox
Drop a TEdit in form an put it as child of TPanel
Ok, I can simply do a sort of Parent.Parent.Click after receive the OnClick on TEdit but imagine now several TScrollBoxes, with different level of nesting using TPanels with a bunch of different controls inside. It doesn't make sense neither adding the onclick code for each control in the tree, nor change the hierarchy of Parent.Parent.Click every time I redesign the layout adding an intermediate parent control.
Is there any way to do this in Firemonkey (either for Windows or MacOS)?
PS: I'm using Delphi 10.2.3 (Tokyo)

Firemonkey and dockable forms

Is it possible to have dockable forms in FireMonkey, as I have inspected the forms properties, and there is no such property to do that.
Is there any workaround to accomplish that?
There's nothing built in, as far as I know but it shouldn't be too difficult to add in yourself. Just bear in mind that any form can parent any control on another form:
On the child form, add any controls inside a container (e.g. a TLayout).
Create the child form.
Set the Parent property of the TLayout (etc.) to the parent form (or, more probably a container on the parent form so you can set the child TLayout's alignment to alClient).
If you want to show the placement during a drag operation, experiment with the various effec ts included.
Unlike VCL, the Firemonkey does not have a built-in dockable interface for creating dock forms. But there is a commercial component for creating a complete dockable interface in FMX. The component implements dockable forms only. So far, the docked document panels are not supported (like the visual studio IDE does) and no docked toolbars. But in general, they have all the necessary functionality, including auto-hide panels and the ability to be saved/restored in/from XML.
https://www.devmachines.com/firedocking-overview.html

Duplicate ControlBox

I have inherited an application that was started as an MDI program, but the necessary background work was never put in place to fully support MDI. I'm trying to build in just enough MDI support to make the application look good and work properly as an SDI application.
Here's what I am observing, and I don't know how this is happening or how to fix it.
The MDIchild form's border is shown above the MDIparent form's menu strip.
The MDIchild form has two icons in the upper left.
The MDIchild form has two ControlBoxes in the upper right.
Any ideas why this would be?
I'd be really happy if the MDIChild window border (including the icons and control boxes) was removed entirely.
Thanks,
SH
I created the child form but showed it in normal state instead of maximized. It's as if showing the parent form in the same process as the maximized child form caused the form to be constructed out of order. My code looked something like this...
frmChild.WindowState = FormWindowState.Normal
frmParent.Show() 'frmChild.Show called within form_load of parent
frmChild.WindowState = FormWindowState.Maximized
And yes, I set the Child window's FormBorderStyle to None, but like I said, I didn't want an MDI application.
I think this must be a bug in Visual Studio. For so many people to have difficulty with it, it can't be right.
I found:
Call Show() on your MDI form before setting the WindowState property on your child form to get rid of the multiple control boxes.
Do not set the WindowState to Maximized in the designer -- do it in code after you've shown the parent.

How to solve non-alignment of Delphi child form within parent form in XP

I have a number of forms that 'host' other forms using ChildForm.Parent := HostForm and ChildForm.Align = alClient etc. Some child forms are host themselves for another child form. Under Windows 7, the alignment is fine but Windows XP sometimes leaves the child form visible but not client aligned. Touch the outer window frame to resize it by one pixel and it all springs aligned correctly. Is there a command I can send to the host form to ensure that the alignment has taken place properly?
You might want to take look at Realign method. Look also at AlignControls and ArrangeControl to manually align the child control. Consider also using Frames instead of Forms if it is possible - they are designed for the job you described (but on the other hand have a number of inconveniences - for example lack of OnCreate event).
Best regards -- Spook.
I also had this problem a few times and it seems it is often caused by faulty controls on the child form.
How to avoid issues when embedding a TForm in another TForm?

AlphaBlend a child form

I'm looking after a way to AlphaBlend a child form, if possible using layered windows as there will be interactive controls behind it.
The problem is I have a component in a regular TForm that paints multiple visual layers (drawings, pictures...). At some point I need to instantiate an editor control on this form (in-place), this control will involve a variety of standard input controls outside of my control (edit box, check box, etc.), however I would like to overlay the layers in front of the layer being edited using alpha blending (and WS_EX_TRANSPARENT to make it click-through).
I first thought of using child forms for that (borderless TForms parented to the component), and that works alright, up to the point where the AlphaBlended TForm isn't alphablended at all, but turns opaque as soon as parented...
I then tried to unparent the alphablended form, set it to fsStayOnTop, and by reacting to the relevant events, keep it in front of the component on screen, that works, but that isn't a truly satisfying solution: the alphablended StayOnTop form is also in front of other modal and modeless forms of the application, should the user decide to move them in front of the component...
So, any other ideas on a way to have a child form be alphablended? (or behave like it is)
According to MSDN you are out of luck, as WS_EX_LAYERED cannot be used for child windows.
Maybe you could hide all editor forms when your form / application loses focus, that would at least keep them from being on top of other windows. Still, it's unsatisfactory...

Resources