1
votes

I use embedded forms in my application and I was trying something like this:

At designtime the form is a normal form which don't know anything about embedding/docking. With a ButtonClick I can make the form visible by calling the Show() method of the form. At runtime it can happen that the form gets docked into another form and becomes an embedded form. When I press the Button for showing the form again (which is now embedded) nothing happens because I have to call Show() for the form which contains the embedded form now.

I am lookin for a method to force showing the parent form when the Show() method of the embedded form is called. I could handle this by checking the existance of a parent form before calling Show() but I don't want to include this specific handling.

I would prefer to do this handling in the parent form wich gets notified when a form is docked.

The Show() method only sets the Visible property to true (RAD Studio Help), so I don't think that a message is fired ...?

Do you know a method to realize something like this?

Edit

I want to put some information about my application because I guess that it is more a designing problem than a programming problem.

The application uses several plugins to adapt to the connected hardware. The exe provides a drag&dock environment and contains a base class for dockable forms. The plugins don't have any knowledge about the docking implementation. By creating a dockable form and embedding a form from the plugin the plugin form becomes dockable. This is the reason why I want do get the parent form shown when somewhere the method Show() of the embedded form is called.

2
Calling Show doesn't do what you want. What you want to do requires something to walk the parent chain to find the top level form, and call Show on that. You want the top level form shown but want to avoid walking the parent chain. Are you prepared for the possibility that what you are asking cannot be done?David Heffernan
Once the child is embedded, The parent could hook to the child form WindowProc by sub-classing it and checking for WM_SHOW etc messages. (Id better use GetParentForm <> nil and simply show it).kobik
@DavidHeffernan Yes I was prepared for this :) I was hoping that the vcl has a mechanism that I don't know yet.Kerem
@kobik: Does WM_SHOW gets fired even when OnShow isn't triggered?Kerem

2 Answers

4
votes

You could create a common ancestor for your embedded forms or even for all forms in the application, and then derive your forms from it:

type
  TEmbeddedForm = class(TForm)
  public
    procedure Show;
  end;

procedure TEmbeddedForm.Show;
var
  ParentForm: TCustomForm;
begin
  inherited Show;
  ParentForm := GetParentForm(Self);
  if ParentForm <> Self then
  begin
    // Form is Embedded
    Update;        
    ParentForm.Show;
    // You might alternatively consider to send custom 
    // message to the Parent form, and let it decide what to do e.g.
    // SendMessage(ParentForm.Handle, CM_MY_EMBEDED_FORM_SHOW, 0, 0);
  end;
end;

Then when you call:

procedure TForm1.Button1Click(Sender: TObject);
begin
  // MyEmbeddedForm is derived from TEmbeddedForm 
  MyEmbeddedForm.Align := alClient;
  MyEmbeddedForm.BorderStyle := bsNone;

  MyEmbeddedForm.Parent := Form3.Panel1;
  MyEmbeddedForm.Show;
end;

Form3 is showing.


Another option (which I only confirmed with Spy++) is to intercept WM_CHILDACTIVATE or WM_WINDOWPOSCHANGING in the TEmbeddedForm. it is sent to it when the child form is calling TEmbeddedForm.Show, and act accordingly i.e. GetParentForm(Self).Show.

0
votes

Use SetFocus instead of Show on the embedded form.

This will enforce showing of the parent form too.