Einzelnen Beitrag anzeigen

Andreas L.

Registriert seit: 23. Mai 2011
Ort: Furth im Wald
308 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Wie erstelle ich dynamische forms richtig ?

  Alt 6. Mär 2019, 10:05
Du musst die Größe des Arrays nicht als Feld/Variable im Form "speichern".

Die Funktion Low liefert den ersten Index des Arrays. High den letzten. Length gibt die Größe aus. Mit Length kannst du übrigens auch die Länge eines Strings ermitteln. Ein String ist intern auch nur ein Array.

Delphi-Quellcode:
   TForm2 = class(TForm)
      ...
      procedure btnCreateChildClick(Sender: TObject);
      procedure FormCreate(Sender: TObject);
   private
      ChildArray: array of Tfrm_Child;
      ContainerActualWidth: integer;
      ContainerActualHeigt: integer;
   end;

...


procedure TForm2.btnCreateChildClick(Sender: TObject);
var
  Index: Integer;
begin
  // Array vergrößern
  SetLength(ChildArray, Length(ChildArray) + 1);

  // Letzten und damit aktuellen Index temporär "speichern"
  // damit nicht ständig High aufgerufen werden muss.
  Index := High(ChildArray);

  // Form erstellen
  ChildArray[Index] := Tfrm_child.Create(Form2);
  ChildArray[Index].Parent := cxScrollbox;
  ChildArray[Index].Align := alLeft;
  ChildArray[Index].AlignWithMargins := True;
  ChildArray[Index].pnlchild.Color := clRed;
  ChildArray[Index].pnlchild.Caption := 'ArrayINDEX =' + IntToStr(Index);
  ChildArray[Index].Show;
end;
Ich würde statt dem Array aber eine TObjectList verwenden.

Delphi-Quellcode:
uses
    ..., ContNrs;

  ...

   TForm2 = class(TForm)
      ...
      procedure btnCreateChildClick(Sender: TObject);
      procedure FormCreate(Sender: TObject);
      procedure FormDestroy(Sender: TObject);
      procedure FormClose(Sender: TObject);
   private
      FChildList: TObjectList;
   protected
      procedure CreateChildList;
      procedure DestroyChildList;
      function NewChildForm: Integer;
   end;

...

procedure TForm2.CreateChildList;
begin
  // Liste erstellen
  // Wird bei Create kein Parameter oder True übergeben
  // verwaltet die Liste alle eingetragenen Objekte
  // d. h. wenn die Liste freigegeben oder ein Eintrag
  // gelöscht wird, wird die / das Form automatisch
  // freigegeben
  FChildList := TObjectList.Create;
  // Wenn du False übergibst bist du selbst
  // verantwortlich die einzelnen Forms/Einträge
  // freizugeben:
  //FChildList := TObjectList.Create(False);
end;

procedure TForm2.DestroyChildList;
begin
  // Wenn OwnsObjects False ist,
  // musst du durch alle Einträge iterieren
  // und die Objekte selbst freigeben bevor
  // die Liste zerstört wird. Das würde so aussehen:
  for FormIndex := FChildList.Count - 1 downto 0 do
    FreeAndNil(FChildList[FormIndex]);
  // Da in CreateChildList nicht False übergeben wurde
  // ist dies nicht nötig.

  FreeAndNil(FChildList);
end;

function TForm2.NewChildForm: Integer;
var
  NewForm: Tfrm_child;
begin
  // Form erzeugen
  NewForm := Tfrm_child.Create(Self);
  try
    // Form der Liste hinzufügen
    // Add gibt den Index des neuen Eintrags zurück.
    Result := FChildList.Add(NewForm);

    // Form Eigenschaften setzen
    NewForm.Parent := cxScrollbox;
    NewForm.Align := alLeft;
    NewForm.AlignWithMargins := True;
    NewForm.pnlchild.Color := clRed;
    NewForm.pnlchild.Caption := 'ArrayINDEX =' + IntToStr(Result);
    NewForm.Show;
  except
    // Wenn ein Fehler auftritt wird -1 zurückgegeben.
    // Sinnvoller wäre es den Fehler zu "verarbeiten".
    Result := -1;
  end;
end;

procedure TForm2.btnCreateChildClick(Sender: TObject);
var
  Index: Integer;
begin
  // Funktion aufrufen um Form zu erstellen
  // Die Funktion gibt den Index des neuen Forms
  // zurück. Den kannst du evtl. brauchen wenn nachträglich
  // das Form geändert werden soll.
  // Wird -1 zurückgegeben konnte das Form nicht erstellt oder
  // nicht der Liste hinzugefügt werden.
  Index := Self.NewChildForm;

  // Überprüfen ob das Form erstellt
  // wurde, ggf. Meldung anzeigen.
  if Index = -1 then
    ShowMessage('Das Form konnte nicht erstellt werden!')
  else
    ShowMessage('Das Form wurde erfolgreich erstellt.');

  // Auf das Form via Index zugreifen
  Tfrm_child(FChildList[Index]).Caption := 'Hallo Welt';
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  // Liste erzeugen
  Self.ChildListCreate;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  // Liste freigeben wenn das Form zerstört wird.
  // Das kann man alternativ auch im OnClose machen.
  Self.ChildListDestroy;
end;
Andreas Lauß
Blog

Geändert von Andreas L. ( 6. Mär 2019 um 10:13 Uhr)
  Mit Zitat antworten Zitat