0

I am working with a Delphi form that contains a TMainMenu. In a particular situation I want to show this form parented and client-aligned inside another form. This works fine but the main menu of the parented form does not appear. I see a comment in this SO question that states "A child window cannot have a menu". Is there anything that I can do to override this behaviour and make a TMainMenu appear?

An aside: I've only just noticed this because where I have used this principle before, I've been using the Developer Express menu component and this is quite happy to show in a child form.

Later edit: Using the code from TLama below, this works (but the child menu is not themed, I,e very plain): This works:

procedure TForm65.FormShow(Sender: TObject);
begin
  Winapi.Windows.SetParent(ChildForm.Handle, Handle); // <<<<<<<<
  ChildForm.BorderStyle := bsNone;
  ChildForm.Align := alClient;
  ChildForm.Show;
end;

This code DOES NOT work. Why?

procedure TForm65.FormShow(Sender: TObject);
begin
  ChildForm.Parent := Self; // <<<<<<<<<
  ChildForm.BorderStyle := bsNone;
  ChildForm.Align := alClient;
  ChildForm.Show;
end;
Community
  • 1
  • 1
Brian Frost
  • 13,334
  • 11
  • 80
  • 154
  • Showing a form in a form is a bit odd (if no MDI interface). What if you replace the form with a Frame? – whosrdaddy May 08 '13 at 10:02
  • 1
    I can't reproduce this. I've tried to use a code [`like this`](http://pastebin.com/kC8mkff7), but the main menu placed on the `ChildForm` remains and works just fine (Delphi 2009). – TLama May 08 '13 at 10:05
  • @whosrdaddy: But it's cool! Sometimes I let my standard controls (e.g. buttons) have window frames just for the fun of it. – Andreas Rejbrand May 08 '13 at 12:14
  • @TLama: Your code does work but the menu is very plain (missing theme?). I would like to know why my Parent assignment fails but yours (nearly) works. – Brian Frost May 08 '13 at 13:58
  • @Brian Calling SetParent doesn't make the window become a child window. This is explained in the documentation for SetParent. My answer is accurate. After all, the documentation on MSDN could not be more clear. – David Heffernan May 08 '13 at 16:15

1 Answers1

3

MSDN makes this perfectly clear:

A child window has a client area but no other features, unless they are explicitly requested. An application can request a title bar, a window menu, minimize and maximize buttons, a border, and scroll bars for a child window, but a child window cannot have a menu.

This refers to the menu as drawn by Windows itself. If your component custom draws a menu bar, then of course it can have a menu, even if it is a child window.


Your call to SetParent does not make your window into a child window. This is explained in the documentation:

For compatibility reasons, SetParent does not modify the WS_CHILD or WS_POPUP window styles of the window whose parent is being changed. Therefore, if hWndNewParent is NULL, you should also clear the WS_CHILD bit and set the WS_ POPUP style after calling SetParent. Conversely, if hWndNewParent is not NULL and the window was previously a child of the desktop, you should clear the WS_POPUP style and set the WS_CHILD style before calling SetParent.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I believe what OP silently wants MDI child window, rather the general child window. It does not make much difference in the menu part, but still... – OnTheFly May 08 '13 at 13:21
  • @david ok I now understand that SetParent is what is wanted and we see that it works. Could you go further now to explain why SetParent behaves differently from ChildForm.Parent := Self? – Brian Frost May 09 '13 at 05:58
  • I already did. It's in the MSDN extract in my answer. You are not setting the WS_CHILD style when you call SetParent. So your window is not a child window. It's still a popup window, WS_POPUP. – David Heffernan May 09 '13 at 07:19