Delphi:使用来自动态表单的 public 程序

Delphi: Use public procedures from a dynamic form

我有一个 Delphi XE+ 应用程序,其中包含 3 个表单,其中 2 个是动态创建的,如下所示:

form_main -> form_equip -> form_certif

第 1:打开 form_equip

procedure Tform_main.button_equip_addClick(Sender: TObject);
var 
  form_equip: Tform_equip;
begin
  form_equip:= Tform_equip.Create(Self);
  form_equip.equip_id:= 0;
  form_equip.ShowModal;
  FreeAndNil(form_equip);
end;

form_equip 我有一个 public procedure has_changes

第 2 次:打开 form_certif

procedure Tform_equip.button_certif_addClick(Sender: TObject);
var
  form_certif: Tform_certif;
begin
  form_certif:= Tform_certif.Create(Self);
  form_certif.index:= 0;
  form_certif.ShowModal;
  FreeAndNil(form_certif);
end;

现在,当我从 form_certif

按下确定按钮时
procedure Tform_certif.button_okClick(Sender: TObject);
begin
  //do something...

  form_equip.has_changes; //this public procedure from form_equip is not visible because form was created as local var on form_main
end;

问题是,如何将 sender/parent 名称传输到 form_certif,这样我才能从 form_equip 中看到 public 过程和变量?

一个简单的方法是在 unit_equip 内部声明为全局:

var 
  form_equip: Tform_equip

但我避免这样做,因为 form_equip 可以在多个 windows 中以不同的名称动态打开...

在构造函数中将信息作为参数传递。像这样声明构造函数:

constructor Create(AOwner: TComponent; const ParentName: string);

在构造函数的实现中,记下传递的名称。

将所有需要的信息从 form_equip 传递到 form_certif。这样 form_certif 就与 form_equip.

的任何依赖关系解耦了
procedure Tform_equip.button_certif_addClick(Sender: TObject);
var
  form_certif: Tform_certif;
begin
  form_certif:= Tform_certif.Create(nil);
  try
    form_certif.index:= 0;
    // Pass all other needed variable values to form_certif
    // including callback methods
    form_certif.Has_Changes_Method := Self.Has_Changes();
    if form_certif.ShowModal = mrOk then
    begin
      // take care of changes
    end;
  finally
    FreeAndNil(form_certif);
  end;
end;

这就是 form_certif 单元中的样子:

type
  THas_Changes_Method = procedure of Object;
  TForm_Certif = class(TForm)
  ...
  private
    FIndex: Integer;
    FHasChanges: THas_Changes_Method;
  public
    property Index: Integer read FIndex write FIndex;
    property Has_Changes_Method: THas_Changes_Method read fHasChanges write fHasChanges; 
  end;

由于您是在代码中创建表单,因此您可以向表单添加自定义构造函数并将其他表单作为参数传递。

Tform_certif = class(TForm)
...
protected
  form_equip: Tform_equip;
public
  constructor Create(AOwner: TComponent; Aform_equip: Tform_equip); reintroduce;
end;

constructor Tform_certif.Create(AOwner: TComponent; Aform_equip: Tform_equip);
begin
  inherited Create(AOwner);
  form_equip := Aform_equip;
end;

所以现在您可以调用 form_equip.has_changes,因为它是您在构造 Tform_certif 表单期间初始化的字段,它指向创建此表单的 Tform_equip 的特定实例Tform_certif.

的特定实例
procedure Tform_certif.button_okClick(Sender: TObject);
begin
  //do something...

  // test whether form_equip is assigned to avoid AV by calling methods on nil object 
  if Assigned(form_equip) then form_equip.has_changes;
end;

要创建您的 Tform_certif,您将使用以下代码

procedure Tform_equip.button_certif_addClick(Sender: TObject);
var
  form_certif: Tform_certif;
begin
  form_certif:= Tform_certif.Create(Self, Self);
  form_certif.index:= 0;
  form_certif.ShowModal;
  FreeAndNil(form_certif);
end;

上面的构造函数代码还有一种变体,只需要传一个参数,然后在构造函数中测试AOwner是否是Tform_equip类型,不需要改button_certif_addClick 中的代码用于使用那种解决方案。

Tform_certif = class(TForm)
...
protected
  form_equip: Tform_equip;
public
  constructor Create(AOwner: TComponent); override;
end;

constructor Tform_certif.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  if AOwner is Tform_equip then form_equip := Tform_equip(AOwner);
end;