4

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)

tshepang
  • 12,111
  • 21
  • 91
  • 136
Brian Frost
  • 13,334
  • 11
  • 80
  • 154
  • 1
    Why are you going so far out of your way to not use MDI, when you obviously want MDI, in the end? I hate MDI, how it looks, how it works, etc etc. It's a terrible concept from a usability and UI interaction design point of view. But if you actually WANT mdi's horrible looks, then just USE mdi! :-) – Warren P Apr 20 '11 at 18:32
  • 1
    @warren sometimes mdi is exactly what you need and works beautifully – David Heffernan Apr 20 '11 at 20:43
  • @WarrenP MDI is horrible? Well, that's what they say... But for most of my biz apps, I need them. Unfortunately I cannot use them as my software are designed for both Windows and Ubuntu. So I've got to do without them. Another thing... I'm using Lazarus (well they say it's the same, but... you know) ;) – itsols Nov 03 '12 at 04:19

3 Answers3

5

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.

Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
  • @SertacAkyuz Is there a workaround that does not depend on the windows API? I'm targeting Ubuntu/Windows app developement with Lazarus and have the SAME issue. So perhaps we're doing the parent setting the incorrect way. – itsols Nov 03 '12 at 04:22
  • Purely experimental... In my case I wanted the child form to just show and not be movable out of the parent container. If you guys needs to do the same, I've achieved this by using PAGECONTROL with a single tab. Turn off the child form's borders and it works. BUT you cannot move the child form around, obviously. For now, this serves my purpose :) – itsols Nov 03 '12 at 06:20
4

Call Windows.SetFocus(Form.Handle) which is somewhat more forceful than TForm.SetFocus. Specifically Windows.SetFocus will focus and activate a form that is inactive which I suspect is your main problem.

Having more than one form active feels wrong.

Finally, did you consider using MDI? It still works.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Yes, I did consider MDI but I wanted to avoid both the complication and possible future deprecation. – Brian Frost Apr 21 '11 at 07:13
  • 1
    I think deprecation is unlikely. Latest documention is more encouraging for new apps. MDI is not at all complicated in Delphi. All the work is done for you. – David Heffernan Apr 21 '11 at 07:17
0

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

That's it, this way you dont have to set the parent to make it work.

Gerry Coll
  • 5,867
  • 1
  • 27
  • 36
Cesar
  • 500
  • 5
  • 12
  • Nice one to have in a comment, but does not answer any of the questions otherwise.. – Sertac Akyuz Apr 20 '11 at 12:23
  • 1
    Ordinarily I'd agree, but there seems to be a key requirement that I don't think traditional MDI can handle: "Out of my edit mode, the borders disappear and the child forms are fixed in position." – Disillusioned Apr 20 '11 at 22:23