Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Procedurepointer übergeben (https://www.delphipraxis.net/168761-procedurepointer-uebergeben.html)

RedOne 8. Jun 2012 17:57

Delphi-Version: 2009

Procedurepointer übergeben
 
Hallo zusammen

Ich stehe bei einem Problem an bei dem Ihr mir sicher helfen könnt.
Und zwar folgendes:

Vereinfacht gesagt habe ich ein Formular auf dem ich die Klasse TFirst instanziere. Dieses Objekt wiederum instanziert die Klasse TSecond. TSecond ist ein Panel (im Beispiel unterhalb die vereinfachte Version ohne Panel). Wird auf diesem Panel ein Button geklickt, soll eine Funktion auf dem Hauptformular ausgeführt werden.
Beim kreieren der Klasse TFirst weisst TFirst TSecond die Methode aus dem Hauptformular zu. Aber: Diese ist zu diesem Zeitpunkt noch nicht zugewiesen. Klingt verwirrlich, deshalb hier ein vereinfachtes Beispiel (habe auf Objektfreigaben etc. absichtlich verzichtet).

Delphi-Quellcode:
type

  TClick = procedure of object;

  TFirst = class
  private
    FClick: TClick;
  public
    constructor Create;
    property DoIt: TClick read FClick write FClick;
  end;

  TSecond = class
  private
    FClick: TClick;
    procedure InternalClick( _sender: TObject );
  public
    property DoIt: TClick read FClick write FClick;
    constructor Create;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
  private
    procedure DoItLocal;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//------------------------------- TFirst

constructor TFirst.Create;
var
  c: TSecond;
begin
  c:= TSecond.Create;
  c.DoIt:= FClick; //FClick ist zu diesem Zeitpunkt noch nil
end;

//------------------------------- TSecond

constructor TSecond.Create;
begin
  Form1.Button1.OnClick:= InternalClick; //Hässliche Implementierung, ich weiss, dient aber auch zur zur Veranschaulichung :-)
end;

procedure TSecond.InternalClick(_sender: TObject);
begin
  //Hier sollte die Procedur "DoItLocal" auf Form1 ausgeführt werden, ist aber nil da die Procedure beim Create noch nicht zugewiesen war
  if Assigned( FClick ) then begin
    FClick;
  end;
end;

//------------------------------- TForm1

procedure TForm1.DoItLocal;
begin
  ShowMessage('Event ausgelöst');
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  e: TFirst;
begin
  e:= TFirst.Create; //Innerhalb dem Create wird die Procedure zugewiesen. Diese ist aber nil, da die Procedure der Klasse TFirst erst eine Zeile tiefern zugewiesen wird...
  e.DoIt:= Self.DoItLocal;
end;
Meiner Meinung nach muss ich nun statt der Procedure den Pointer über/weitergeben. Aber wie...?

Herzlichen Dank!

RedOne

jaenicke 8. Jun 2012 21:44

AW: Procedurepointer übergeben
 
Theoretisch kann man natürlich einen Pointer benutzen, aber das macht hier wohl weniger Sinn.

Es gibt z.B. diese Lösungen:
  • Erstelle in TFirst eine Methode, die du dann dem Event der Instanz von TSecond zuweist. In der Methode kannst du dann später wiederum den Eventhandler aufrufen.
  • Oder TFirst kennt die Instanz von TSecond, z.B. in einem privaten Feld. Dann kannst du im Setter des Events das Event auch bei TSecond zuweisen.

swkevin08 8. Jun 2012 21:59

AW: Procedurepointer übergeben
 
Übergebe doch beim Konstruktor dein "Self.DoItLocal" und dann deiner TSecond Instanz.

Code:
constructor TFirst.Create(click: TClick);
var
   c: TSecond;
begin
   c:= TSecond.Create;
   c.DoIt:= click;
end;

RedOne 9. Jun 2012 11:40

AW: Procedurepointer übergeben
 
Merci für Eure Antworten.
Über den Konstruktur möchte ich die Procedure nicht übergeben, da es noch eine unbestimmte Anzahl an zusätzlichen Prozeduren geben könnte.
Aber so wie es Jaenicke geschrieben hat ist es am einfachsten... vielen Dank, das hat geholfen :-)

Gruss
RedOne


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz