AlphaBlend a child form - delphi

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...

Related

Add shortcut to a TForm or Panel.Transparent?

To thwart the nit-pickers, let me start with, I searched here with this and could not find an answer, and yes, also I did scroll through the "Similar questions."...
Adding shortcuts to a TForm
I want to drag and drop some shortcuts from the Desktop to a TForm in my application. I am using Anders Melander's brilliant Drag Drop Suite (DDS).
I tried putting a TImage on the form but the DDS does not drop to an Image so I added a TPanel with a TImage on it. I could then drop on the panel and assign the image to the TImage.Picture. Problem was the Panel has no Transparent Property so the shortcut on the form looks clunky with the visible Panel behind it.
I need to be able to drop to the TImage or make the underlying TPanel transparent.
Can anyone help with code-snippets for either of those options, or better yet, a method of dropping a Shortcut directly on to my Form.
Thanks
Coincidentally I needed to make a TWinControl (the base for every visible control with a window handle, including TPanel) transparent. I found numerous results and applied them to this answer.
It's been a while since I implemented drag and drop, but I assume you call some API and pass it the handle of the panel? That answers the question why you can't use TImage. TImage is a graphic control, a control without a handle, that relies on its parent for recieving messages and drawing itself.
It should be possible to use the form, though, since that has a handle too.
If the TImage is directly on the TForm, then let the TForm handle the drop, no TPanel needed. OLE Drag&Drop operations (which Ander's components implement) provide coordinates where dragging and dropping occurs. The TForm should be able to detect when a drag is over the area occupied by the TImage and what type of data is being dragged, and only allow dropping of supported types within that area, extracting the dropped data and updating the TImageas needed, and denying anything else that does not match that criteria.

MDI interface with FireMonkey

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).

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?

Design-time drag and drop in Delphi?

Before Delphi 2006 (I think) introduced the TFlowPanel and TGridPanel, I did a control that was similar in concept. It still does a couple of things those controls do not do, and when upgrading my code to Delphi 2009, I decided to add a couple of enhancements to that as well.
Right now, the order of the child controls is determined by their creation order. The FlowPanel and GridPanel show a better way with ControlIndex and other filtered properties, but I was wondering if there is a way to handle drag and drop reordering in design-time? As far as I can tell, dragging an edit control and dropping it onto my panel doesn't call anything that I can access at design-time.
I was half-fantasising about a way to either detect the drop operation directly, or to perhaps detect when a control is moved so I can determine where it should go.
Any ideas?
Update:
OK, got it working. The container control was already overriding AlignControls to manage the placement of the controls. When you drag the nested control and drop it, AlignControls is again called. I then compared the new coordinates of the control with the other controls in the list and moved it to the appropriate position.
There were a couple of problems that I had to work through (mostly related to the many calls to AlignControls) but the basic concept is simple enough. Thanks to all the commenters for all the help.
You can't drag a control that's already on the form and drop it onto your panel. Dragging is only for moving a control, not for changing its parent. To change the parent, cut and paste.
If the control is already on your panel, and you want to move it to another position on your panel, then the panel can control the layout by overriding the TWinControl.AlignControls method. When a control is moved, its SetBounds method is called, and among the things tha happens is that it calls AlignControl(Self) on its parent window. That calls AlignControls. Look in Controls.pas, and you'll see that that's a complicated method, but it's what is responsible for the layout of the children on a control, and that's exactly what you're planning to change.
Perhaps some of these suggestions might help.
You can re-parent a control in the designer without having to do cut-and-paste. View the structure pane, and simply drag the visual control to the node of another parent in the structure pane. If you have things in a flowpanel, drag everything out of the flow panel and drag them back in the order that you want them to be.
(You can re-parent ANY visual control this way, without changing anything other than its parent. I highly recommend doing it this way.)
You can view the form as text, and move the declaration order around in there -- but obviously you'll need to be careful when editing the "resource" file directly.
You can set tab order in the designer, so you could make a different control based on tab order that works as you want. You can right click on the form and change the creation order of the non-visual controls, but that doesn't work with visual controls.
Have you tried to write an "OnDragDrop" event for your grid component, where you check if your component is in design mode?
I haven't written such a component yet, but I don't see why the event shouldn't trigger.

Resources