How to Create MDI Child of different type with Generics?

Viewed 205

I need to centralize the MDI Child Forms creation into a unique procedure in Delphi (VCL). The idea is to do some actions every time an MDI Child Form is created no matter its type, i.e., to add its caption name into a List to get access to that MDI child form. Like this:

   procedure TMainForm<T>.CreateMDIChild(const ACaption : String);
    var
      Child: T;
    begin
      { create a new MDI child window }
      Child := T.Create(Application);
      Child.Caption := ACaption;
      // add this child to the list of active MDI windows
      ...
    end;

   procedure TMainForm.Button1Click(Sender : TObject);
   begin
       CreateMDIChild<TMdiChild1>('Child type 1');
       CreateMDIChild<TMdiChild2>('Child type 2');
       ...

But, I don't have experience with generics. Any help I'll appreciate it. Thank you so much.

2 Answers

You can use classes from unit System.Generics.Collections. For example, for resolving similar task I use TObjectList<TfmMDIChild>, where TfmMDIChild my own class. Another useful tip you can make your own class for holding collection based on TObjectList. I made something like this:

  TWindowList = class(TObjectList<TfmMDIChild>)
  public
    procedure RefreshGrids;
    function FindWindow(const AClassName: string; AObjCode: Integer = 0): TfmMDIChild;
    procedure RefreshWindow(const AClassName: string; AObjForRefresh: integer = 0; AObjCode: Integer = 0);
    procedure RefreshToolBars;
  end;

You can define a class for generic creation of form (using generics) with a class constraint like this:

TGenericMDIForm <T:TForm> = class
  class procedure CreateMDIChild(const Name: string);
end;

And with this implementation:

class procedure TGenericMDIForm<T>.CreateMDIChild(const Name: string);
var
  Child:TCustomForm;
begin
  Child := T.Create(Application);
  Child.Caption := Name + ' of ' + T.ClassName + ' class';
end;

Now, you can use it for create MDIChil forms differents classes:

procedure TMainForm.Button1Click(Sender: TObject);
begin
   TGenericMDIForm<TMdiChild>.CreateMDIChild('Child type 1');
   TGenericMDIForm<TMdiChild2>.CreateMDIChild('Child type 2');
end; 

Using the class constraint with the generic TGenericMDIForm <T:TForm> = class, you can avoid someone try use something like this TGenericMDIForm<TMemo>.CreateMDIChild('Child type 1'); with a class that not is a TForm descendant.

Related