Delphi Form with custom constructor as the mainform?

旧时模样 提交于 2019-12-11 00:42:37

问题


I want to have a MainForm that is derived from a BaseForm that has a custom constructor. Since this is the Mainform, it is created by a call to Application.CreateForm(TMyMainForm, MyMainForm) in the *.dpr file. However, my custom constructor is not called during form creation.

Obviously, it works fine, if I call MyMainForm := TMyMainForm.Create(AOwner). Can I not use a form with custom constructor as the main form ?

TBaseForm = class(TForm)
  constructor Create(AOwner:TComponent; AName:string);reintroduce;
end;

TMyMainForm = class(TBaseForm)
  constructor Create(AOwner:TComponent);reintroduce;
end;  

constructor TBaseForm.Create(AOwner:TComponent);

begin;
  inherited Create(AOwner);
end;

constructor TMyMainForm.Create(AOwner:TComponent);

begin;
  inherited Create(AOwner, 'Custom Constructor Parameter');
end;  

回答1:


Application.CreateForm() cannot call a reintroduce'd constructor. When creating a new object, it calls the TComponent.Create() constructor and expects polymorphism to call any derived constructors. By reintroduce'ing your custom constructor, you are not part of the polymorphic call chain. reintroduce exposes a completely new method that simply has the same name as an inherited method but is not related to it.

To do what you are attempting, don't use reintroduce for your constructors. Create a separate constructor in your Base form, and then have your MainForm override the standard constructor and call your custom Base constructor, eg:

TBaseForm = class(TForm)
  constructor CreateWithName(AOwner: TComponent; AName: string); // <-- no reintroduce needed since it is a new name
end;

TMyMainForm = class(TBaseForm)
  constructor Create(AOwner: TComponent); override; // <-- not reintroduce
end;  

constructor TBaseForm.CreateWithName(AOwner: TComponent; AName: string);
begin;
  inherited Create(AOwner);
  // use AName as needed...
end;

constructor TMyMainForm.Create(AOwner: TComponent);
begin;
  inherited CreateWithName(AOwner, 'Custom Constructor Parameter');
end;  



回答2:


In order for a form to become the VCL main form, it must be created via a call to Application.CreateForm. That in turn calls the virtual constructor declared in TComponent. So, there's no way to get a different constructor to be called for the VCL main form.

One option is that presented by Remy. To override the constructor declared in TComponent, and call a different constructor passing extra parameters. That can be a constructor in the same class, or an inherited constructor from a base class.

Another option here would be to use abstract class methods on a base class. For instance,

type
  TMainFormBase = class(TForm)
  protected
    class function ProjectName: string; virtual; abstract;
    class function RegKeyPath: string; virtual; abstract;
  end;

In your derived classes you would override these abstract methods. Instead of setting properties in the constructor, code in the base form class could just call these methods. Of course, if you needed to do work in the constructor, you could perfectly well call these methods from the constructor.

Personally I have a prejudice against adding new constructors to classes that already have virtual constructors. The virtual constructor paradigm leads you towards using that single virtual constructor, and nothing else. If you start adding different constructors further down the hierarchy then it's just all too easy to end up with trouble caused by the wrong constructor being called when instantiating virtually.



来源:https://stackoverflow.com/questions/26132808/delphi-form-with-custom-constructor-as-the-mainform

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!