Einzelnen Beitrag anzeigen

Guido Eisenbeis

Registriert seit: 9. Apr 2006
389 Beiträge
 
Delphi 10.3 Rio
 
#10

Re: "inherited" für umgeleitetes Event

  Alt 17. Mär 2007, 15:58
Hallo Christian.

Du hast scheinbar ein gutes Händchen dafür, wann ich welche Infos brauche!
Die haben geholfen!

Nun zum neuesten Stand:

Mittlerweile habe ich meinen eigenen Code überarbeitet und fertiggestellt und deinen Code verstanden. Die Bearbeitung meines Codes habe ich durchgeführt, bevor ich deinen Code studiert habe. Ich suchte zum einen nach einer einfacheren Lösung, zum anderen wollte ich verstehen was gemacht wird. Der Hammer ist nun, dass mein Code vom Prinzip her fast mit deinem Code identisch ist!


Wie gesagt, danach habe ich deinen/euren Code studiert. Davon habe ich auch alles verstanden bis auf eins:

In Unit1 wird ein Feld "FButon1EventHandler" angelegt. Bis hierhin ist das klar. Dann wird aber noch ein Property "Buton1EventHandler" angelegt, das lediglich in das Feld hineinschreibt oder daraus ausliest. Wozu dient der indirekte Weg über dieses Property?


Zu meinem Code:

Er hat nicht die Komfort-Features deines Codes, wie zum Beispiel "Reset". Dafür ist er einfacher gehalten. Und so sieht er aus:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Label1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Unit2;

procedure TForm1.FormCreate(Sender: TObject);
begin
  InitClickEventRetouring(Label1);
  InitClickEventRetouring(Button1);
end;

procedure TForm1.Label1Click(Sender: TObject);
begin
  ShowMessage('Original-Event von (Label): ' + TLabel(Sender).Name);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage('Original-Event von (Button): ' + TButton(Sender).Name);
end;

end.
Delphi-Quellcode:
unit Unit2;

interface

uses
  StdCtrls;

procedure InitClickEventRetouring(Ctrl: TObject);

implementation

uses
  Dialogs, Classes;

type
  TClickEvnt = procedure (Sender: TObject) of object;
  TMyEventReceiver = class
    private
      FClickOrig: TClickEvnt;
      procedure ClickIntern(Sender: TObject);
    public
      property OnClickOrig: TClickEvnt read FClickOrig write FClickOrig;
  end;

var
  MyEventReceiver: TMyEventReceiver;

procedure TMyEventReceiver.ClickIntern(Sender: TObject);
begin
  ShowMessage('Umgeleitetes Event von: ' + TButton(Sender).Name);
  OnClickOrig(Sender);
end;

procedure InitClickEventRetouring(Ctrl: TObject);
begin
  MyEventReceiver := TMyEventReceiver.Create; // <- "Knackpunkt" !
  MyEventReceiver.OnClickOrig := TButton(Ctrl).OnClick;

  TButton(Ctrl).OnClick := MyEventReceiver.ClickIntern;
end;

initialization

finalization
  MyEventReceiver.Free;

end.
Als ich den Code erstellte, wollte ich ihn so anlegen, dass mehrere (verschiedene) Controls benutzt werden können. Wie man sehen kann, sind auch zwei Init-Aufrufe im FormCreate der Unit1. Einer für Label1 und einer für Button1. Zu diesem Zweck hatte ich vor, ein Array oder eine Liste mit MyEventReceiver-Instanzen zu erstellen.

Während des Programmierens kompiliere ich das Projekt bei bestimmten Gelegenheiten, um Fehler zu ermitteln die der Compiler erkennt. Als ich den obigen Code kompilierte, hatte ich eigentlich erwartet, dass entweder der Compiler an der mit "Knackpunkt" markierten Stelle einen Fehler wirft, oder dass der zweite Init-Aufruf mit der Create-Zuweisung den Wert in "MyEventReceiver" überschreibt. Dem war jedoch nicht so! Alles funktionierte einwandfrei, das jeweilige ClickInner wurde ausgelöst und das richtige Original-OnClick aufgerufen!

Die brennende Frage ist nun: Warum funktioniert das? Oder funktioniert es nicht wirklich?

Beim ersten Create wird Speicher reserviert. Wird vielleicht beim zweiten Create der neu reservierte Speicher wirklich reserviert und der vorherige ist nur "zufällig" noch da, bis ihn irgendein sonstiger Befehl oder ein anderes Programm überschreibt? Und wenn im fialization-Abschnitt "MyEventReceiver" freigegeben wird, wird dann auch sämtlicher Speicher freigegeben? Also auch der vom ersten Create?

Gruß.
Guido.
  Mit Zitat antworten Zitat