How to create a delphi form containing several child forms that can be moved / resized and shown activated

I created a form containing one or more child forms. In my edit mode, each child form displays its own border and title bar, allowing you to move and resize (a bit like the old MDI application). Borders disappear from my editing mode, and child forms are locked in position. For my simple demonstration, I create child forms this way:

procedure TForm1.Button1Click(Sender: TObject); var Frm : TForm; begin Frm := TForm3.Create( Self ); Frm.Parent := Self; Frm.Visible := True; 

The result is the following layout: Layout

I noticed that child form editing controls are never active. I would like the clicked form to display the active title color, just as active applications move when clicked. I assume that my "corpse" behavior of child forms is that they are inactive, but trying to do things like ChildForm.SetFocus does nothing.

What do I need to do so that these edit controls are alive and to show one of the forms as "selected"?

(I would really like to โ€œselectโ€ more than one form, if possible)

+4
source share
3 answers

What causes the behavior is the VCL parental control mechanism. I donโ€™t know the exact reason, it will take some time to understand this, I think, since this is a somewhat complicated mechanism.

You can get the desired behavior using parental control using api:

 procedure TForm1.Button1Click(Sender: TObject); var Frm : TForm; begin Frm := TForm3.Create( Self ); // Frm.Parent := Self; windows.SetParent(Frm.Handle, Handle); Frm.Visible := True; 


You will probably lose some synchronization with VCL, such as parent dependent properties, binding, ownership, etc. This can even be problematic with regards to api, for example, the missing WS_CHILD flag ... Try this and see if it works for your needs.


To have more than one active form, you can tell each of them: "/ p>

  SendMessage(Frm.Handle, WM_NCACTIVATE, WPARAM(True), 0); 

When any form receives this message, it will redraw its non-client area to reflect its (presumably) activated status. Passing false for wParam will do the opposite.

+4
source

A call to Windows.SetFocus(Form.Handle) , which is slightly more powerful than TForm.SetFocus . In particular, Windows.SetFocus will focus and activate an inactive form, which I suspect is your main problem.

Having more than one active form seems wrong.

Finally, have you considered using MDI? It still works.

+3
source

I think that MDI is the easiest way, in the main form is set FormStyle = fsMDIForm, in childs FormStyle = fsMDIChild.

To do this, you do not need to set the parent to work.

0
source

Source: https://habr.com/ru/post/919632/


All Articles