saintfalcon
saintfalcon

Reputation: 117

Delphi - Create Custom Form Instance (Having Custom Constructor Create) From String Form Name

I'm currently confused about creating form using string form name (as in Is there a way to instantiate a class by its name in delphi?) but my form has it's own constructor create.

//-BASE CLASS-//
TBaseForm = class(TForm)
  constructor Create(param1, param2: string); overload;
protected
  var1, var2: string;    
end;

constructor TBaseForm.Create(param1, param2: string);
begin
  inherited Create(Application);
  var1 := param1;
  var2 := param2;
end;

//-REAL CLASS-//
TMyForm = class(TBaseForm)
end;

//-CALLER-//
TCaller = class(TForm)
  procedure Btn1Click(Sender: TObject);
  procedure Btn2Click(Sender: TObject);
end;

uses UnitBaseForm, UnitMyForm;

procedure TCaller.Btn1Click(Sender: TObject);
begin
  TMyForm.Create('x', 'y');
end;

procedure TCaller.Btn1Click(Sender: TObject);
var PC: TPersistentClass;
    Form: TForm;
    FormBase: TBaseForm;
begin
  PC := GetClass('TMyForm');

  // This is OK, but I can't pass param1 & 2
  Form := TFormClass(PC).Create(Application);

  // This will not error while compiled, but it will generate access violation because I need to create MyForm not BaseForm.
  FormBase := TBaseForm(PC).Create('a', 'z');
end;

Based on the code I provided, how can I create a dynamically custom constructor form just by having string form name? Or it's really impossible? (I started to think it's impossible)

Upvotes: 3

Views: 4150

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596352

You need to define a class of TBaseForm data type and then type-cast the result to GetClass() to that type, then you can invoke your constructor. You also need to declare your construuctor as virtual so derived class constructors can be called correctly.

Try this:

type
  TBaseForm = class(TForm)
  public
    constructor Create(param1, param2: string); virtual; overload;
  protected
    var1, var2: string;    
  end;

TBaseFormClass = class of TBaseForm;

.

procedure TCaller.Btn1Click(Sender: TObject);
var
  BF: TBaseFormClass;
  Form: TBaseForm;
begin
  BF := TBaseFormClass(GetClass('TMyForm'));
  Form := BF.Create('a', 'z');
end;

Upvotes: 3

Related Questions