(portuguese)

From my point of view, one thing that is really missing for Delphi/Lazarus is a better application’s form management. Two problems: an independent public variable is used to control an instance, and the ‘please place everything within the form’ approach. The first one requires the programmer to either create the form at the start of the application and not destroy it anymore, or it requires the programmer to create the forms and keep track of object destruction insuring that no variable points to a destroyed object. The second, among other problems, requires that the first one works perfectly so that the communication between forms can work.

When using the second approach there is not much work to be done. You either have to live with this limitation or write a new framework to go around it. Now, in order to maintain an up-to-date public variable, the programmer can benefit from the small tricks I will be describing here.

My suggestion to maintain an up-to-date public variable is to give it to a class method. This method takes care to create the form when this is necessary, and to update the variable when the form is destroyed. For this, implement the following method in the forms base class, in other words, the one from which all the forms will inherit:

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

And implement the method like this:

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;

what is still needed is to make the public variable references nil the moment the form is destroyed. You can choose from two events, either Destroy or Close. I will implement the Destroy, and leave the Close implementation for the programmer, either if he is going to assign caFree to the Action param or destroy the form manually:

procedure TBaseForm.FormDestroy(Sender: TObject);
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;
end;

Finally, the StringList needs to be declared, and destroyed when the application is closed:

implementation

var
  _Forms: TStringList = nil;

...

initialization

finalization
  _Forms.Free;

end.

Done. The only thing needed is to create new forms that descend from this one and call TYourForm.Execute(YourForm). When the form is destroyed, the public variable will be assigned to nil.