(english)

Ao meu ver, uma parte mal elaborada do Delphi/Lazarus é o gerenciamento de formulários da aplicação. Tanto o fato de usar uma variável pública independente para controlar a instância quanto a isca ‘jogue tudo no form’ trazem problemas. A primeira abordagem exige que o programador, ou crie os formulários no início da aplicação e não os destrua mais, ou exige que ele cuide para não deixar a variável apontar para um objeto destruído. A segunda abordagem, entre outros problemas, exige que a primeira funcione perfeitamente para que ocorra comunicação entre formulários.

Quanto a segunda abordagem não há muito o que fazer. Ou convive-se com a limitação ou escreve-se um novo framework para contorná-la. Agora, para manter a variável pública atualizada, o programador pode beneficiar-se de pequenos truques como o que eu vou citar aqui.

A minha sugestão para manter a variável pública atualizada é passá-la para um método de classe. Este método cuida de inicializar o form caso necessário, e cuida de atualizar a variável quando o form for destruído. Para isto, implemente o seguinte método na classe base dos formulários, ou seja, aquela classe a partir da qual todos os forms irão herdar:

  TBaseForm = class(TForm)
  public
    destructor Destroy; override;
    class procedure Execute(var AForm; AModal: Boolean = False);
  end;

a implementação dos métodos fica assim:

class procedure TBaseForm.Execute(var AForm; AModal: Boolean);
var
  VIndex: Integer;
begin
  if not Assigned(_Forms) then
  begin
    _Forms := TStringList.Create;
    _Forms.Sorted := True;
  end;
  if not _Forms.Find(ClassName, VIndex) then
    VIndex := _Forms.Add(ClassName);
  if TForm(AForm) = nil then
    Application.CreateForm(Self, AForm);
  _Forms.Objects[VIndex] := TObject(@AForm);
  if AModal then
    TForm(AForm).ShowModal
  else
    TForm(AForm).Show;
end;

e associar nil à variável pública do form no momento em que ele for destruído:

destructor TBaseForm.Destroy;
type
  PForm = ^TForm;
var
  VIndex: Integer;
begin
  if Assigned(_Forms) and _Forms.Find(ClassName, VIndex) and
   (_Forms.Objects[VIndex] <> nil) then
  begin
    PForm(_Forms.Objects[VIndex])^ := nil;
    _Forms.Objects[VIndex] := nil;
  end;
  inherited;
end;

Por fim, falta declarar a StringList e destruí-la no encerramento da aplicação:

implementation

var
  _Forms: TStringList = nil;

...

initialization

finalization
  _Forms.Free;

end.

Pronto. Agora basta criar novos forms que descendam deste e chamar TSeuForm.Execute(SeuForm). Quando o form for destruído, a variável pública irá apontar para nil.