delphic++buildervcltform

Calling Show() of embedded form should show parent form


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.


Solution

  • 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.