Delphi: использование общедоступных процедур из динамической формы

У меня есть приложение Delphi XE+ с 3 формами, 2 из которых создаются динамически, например:

  • form_main запускает form_equip
  • form_equip запускает form_certif

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 у меня есть общедоступная 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;

Вопрос в том, как я могу передать имя отправителя/родителя в form_certif, чтобы я мог видеть общедоступные процедуры и переменные из form_equip?

Простой способ — объявить внутри unit_equip глобальным:

var 
  form_equip: Tform_equip

но я избегаю этого, потому что form_equip создан для динамического открытия в нескольких окнах с разными именами...


person REALSOFO    schedule 28.03.2015    source источник


Ответы (3)


Передайте всю необходимую информацию от 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;
person LU RD    schedule 28.03.2015

Передайте информацию как параметр в конструкторе. Объявите конструктор следующим образом:

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

В реализации конструктора запишите переданное имя.

person David Heffernan    schedule 28.03.2015

Поскольку вы создаете формы в коде, вы можете добавить в форму собственный конструктор и передать другую форму в качестве параметра.

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;
person Dalija Prasnikar    schedule 28.03.2015