Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a delphi form containing multiple 'child' forms that can be moved/sized and show activated

I've created a form that hosts one or more 'child' forms. In my edit mode, each child form shows its border and caption bar allowing it to be moved and sized (a bit like the old MDI app). Out of my edit mode, the borders disappear and the child forms are fixed in position. For my simple demo, I'm creating the child forms thus:

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

The result is a layout like this: Layout

I notice that the edit controls in the child forms are never active. I would like to have the 'clicked' form show an active caption bar colour just like active apps move around when clicked. I presume my 'corpse' behaviour of the child forms is because they are inactive but attempts to do things like ChildForm.SetFocus do nothing.

What do I need to do to get these edit controls alive and to show one of the forms as 'selected' please?

(I'd really like to 'select' more than one form too if possible)

like image 469
Brian Frost Avatar asked Feb 24 '23 11:02

Brian Frost


1 Answers

What's causing the behavior is the VCL's parenting mechanism. I don't know the exact reason, would take some time to figure it out I guess since it's somewhat a complicated mechanism.

You can get your desired behavior with parenting by the 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'll lose some synchronization with the VCL for sure, like parent dependent properties, anchoring, ownership etc.. It might even be problematic with respect to the api, like the missing WS_CHILD flag... Try it and see if it works to your needs..


To have a feel of more than one active form, you can tell any of them to paint accordingly:

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

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

like image 66
Sertac Akyuz Avatar answered May 01 '23 16:05

Sertac Akyuz