Einzelnen Beitrag anzeigen

Alexander I

Registriert seit: 16. Mai 2014
18 Beiträge
 
Delphi XE5 Starter
 
#1

Events und SpeicherLeaks bei dynamischen Buttons

  Alt 14. Jul 2015, 11:50
Meine Fragestellung:

Es gibt eine Form1. Diese enthält drei Buttons, ShowForm2 und ShowForm3 und Close.
Es gibt eine Form2. Diese enthält zwei zur Laufzeit mittels TButtonNames erzeugt Buttons Close und ShowForm3.
Es gibt eine Form3. Diese enthält einen zur Laufzeit mittels TButtonNames erzeugten Button Close.

In der Projekt.dpr wird zum Schluss nach Speicherlöchern abgefragt, mit: ReportMemoryLeaksOnShutdown := true;

Es gibt eine Klasse TButtonNames .
Delphi-Quellcode:

type
  TButtonNames = class
  public
   procedure LinkProcedure1(linkedProcedure: TLinkedProcedure);
   function ButtonsForForm2(anzahlButton: integer): TArrayOfTBitBtn;
   function ButtonsForForm3(anzahlButton: integer): TArrayOfTBitBtn;
   destructor destroy; override;
  end;
implementation

var
  handlerKlickEvent: THandlerLinkedProcedure;

destructor TButtonNames.destroy;
begin
  FreeAndNil(handlerKlickEvent);
  for i := 0 to High(fbuttons) do
    FreeAndNil(fbuttons[i]);
  inherited;
end;
procedure TButtonNames.LinkProcedure1(linkedProcedure: TLinkedProcedure);
begin
  handlerKlickEvent := THandlerLinkedProcedure.Create;
  handlerKlickEvent.OnKlick := linkedProcedure;
end;

function TButtonNames.ButtonsForForm2(anzahlButton: integer): TArrayOfTBitBtn;
begin
  for i := 0 to anzahlButton - 1 do
  begin
    fbuttons[i] := TBitBtn.Create(form);
    fbuttons[i].OnClick := handlerKlickEvent.GetKlick;
  end;
end;
function TButtonNames.ButtonsForForm3(anzahlButton: integer): TArrayOfTBitBtn;
begin
  for i := 0 to anzahlButton - 1 do
  begin
    fbuttons[i] := TBitBtn.Create(form);
    fbuttons[i].OnClick := handlerKlickEvent.GetKlick;
   end;
end;
Das Event:
Delphi-Quellcode:
  TLinkedProcedure = procedure(sender: TObject) of object;
  THandlerLinkedProcedure = class
  private
    fLinkedProcedure: TLinkedProcedure;
  public
    property OnKlick: TLinkedProcedure read fLinkedProcedure write fLinkedProcedure;
    procedure GetKlick(sender: TObject);
  end;
Form2 und Form3 erzeugen bei Aufruf die Buttons.
In Form2:
Delphi-Quellcode:
Buttons := TButtonNames.Create;
Buttons.LinkProcedure1(EmpfangeKlick);
Buttons.ButtonsForForm2(2); // oder NamesForForm3(1);
in Form3:
Delphi-Quellcode:
Buttons := TButtonNames.Create;
Buttons.LinkProcedure1(EmpfangeKlick);
Buttons.ButtonsForForm3(1);
beide haben LinkProcedure1(EmpfangeKlick);

EmpfangeKlick sind Prozeduren in Form2 und Form3:
Delphi-Quellcode:
procedure Form2.EmpfangeKlick(Sender: TObject);
begin
  if (Sender = fbuttons[0]) then
    Close;
  if (Sender = fbuttons[1]) then
    ShowForm3;
end;
Wenn jetzt in Form1 auf Button ShowForm3 geklickt wird, erscheint Form3 mit allen erzeugten Buttons, Nämlich der Button „Close“.

Form3 wird durch klick auf „Close“ geschlossen. Form1 mit Klick auf Close geschlossen – Keine SpeicherLeaks werden angezeigt.

Wenn in Form1 auf ShowForm2 geklickt wird, erscheint Form2 mit allen erzeugten Buttons. Nämlich ShowForm3 und Close.
Form2 schließen mit Close. Form1 schließen. - Keine SpeicherLeaks werden angezeigt.

Bei Klick in Form2 auf ShowForm3 wird Form3 angezeigt mit dem Close Button.
Schließen Form3 mit Close, gehts zurück zu Form2. Form2 schließen mit Close. Form1 schließen und
SpeicherLeaks werden angezeigt.


Wenn in TButtonNames eine zweite Variable
handlerKlickEvent2: THandlerLinkedProcedure; erzeugt wird, und eine zweite Prozedure
Delphi-Quellcode:
procedure TButtonNames.LinkProcedure2(EmpfangeKlick);
begin
  handlerKlickEvent2 := THandlerLinkedProcedure.Create;
  handlerKlickEvent2.OnKlick := linkedProcedure;
end;
und aufruf in Form3:
Delphi-Quellcode:
Buttons := TButtonNames.Create;

Buttons.LinkProcedure2(EmpfangeKlick);

Buttons.ButtonsForForm3(1);
Dann werden niemals SpeicherLeaks angezeigt.

Warum muß ich eine zweite Variable und eine zweite procedure in TErzeugeButtons erstellen?
Oder, was was hab ich falsch gemacht?

Danke im voraus.

Geändert von Alexander I (14. Jul 2015 um 13:11 Uhr)
  Mit Zitat antworten Zitat