Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi prozedur aufruf und sender (https://www.delphipraxis.net/10769-prozedur-aufruf-und-sender.html)

LoL 24. Okt 2003 20:43


prozedur aufruf und sender
 
hi

wie man selbst erstellte prozeduren über eine komponete die zur laufzeit erstellt wurde funzt weis ich, aber warum funzt das nicht
Delphi-Quellcode:

procedure machwas(sender : TObject);
...
var radiogroup : TRadiogroup;
...
radiogroup         := TRadioGroup.Create(panel);
radiogroup.Parent  := Pnl_eingabe;
@radiogroup.OnClick := @machwas;
...
procedure machwas(sender : TObject);
begin
  if sender = radiogroup then
    showmessage('radiogroup geklickt');
end;
warum sagt der dann das bei aufruf der prozedur "machwas" der sender nil ist?

APP 24. Okt 2003 20:51

Re: prozedur aufruf und sender
 
Hallo Christoph,
Delphi-Quellcode:
  RadioGroup.OnClick := machwas;
Delphi-Quellcode:
 WITH (Sender AS Tradiogroup) DO
    showmessage('radiogroup geklickt');
sollte es heißen.

Christian Seehase 24. Okt 2003 21:00

Re: prozedur aufruf und sender
 
Moin Lol,

weil die Methoden intern noch einen, unsichtbaren, ersten Parameter übergeben.
Daher stammt der Wert von self.

Deklariere die Prozedure mal so:

Delphi-Quellcode:
procedure machwas(oSelf : TComponent;Sender : TObject);
Du hast immer self ausgelesen.
Da es sich aber um eine Prozedur, und nicht um eine Methode handelt, ist self = nil.

APP 25. Okt 2003 15:19

Re: prozedur aufruf und sender
 
Hallo Christian,

könntest Du Deine Lösung bitte näher erläutern?

Ich muß gestehen, dass ich mit dem Konstrukt
Delphi-Quellcode:
@radiogroup.OnClick := @machwas;
so noch nie gearbeitet habe, und die Zeigeroperation
"@machwas" liefert offensichtlich den Eintrittspunkt
von "machwas".

Hast Du nun daraus geschlossen, dass Christoph noch einen
Parameter mitgeben muß?

Ansonsten sollte ja
Delphi-Quellcode:
RadioGroup.OnClick := machwas;
ausreichend sein, oder?

Christian Seehase 25. Okt 2003 15:48

Re: prozedur aufruf und sender
 
Moin Armin,

ich kann's mal versuchen das zu erläutern.

Angenommen, Du hast eine Methode und eine Prozedur "MachWas", dann könnte das ja z.B. so aussehen:

Delphi-Quellcode:
// Methode:
procedure TIrgendeineKlasse.MachWas(Sender: TObject);
begin
  ShowMessage('HALLO');
end;

// Prozedur
procedure MachWas(Sender: TObject);
begin
  ShowMessage('HALLO');
end;
Auf den ersten Blick sehen die gleich aus.
Nun kannst Du aber in der Methode auch noch mit Hilfe von self auf die Eigenschaften und Methoden der Klasse zugreifen (auch wenn man das meistens nicht mitschreibt um so zuzugreifen, da der Compiler dies intern automatisch animmt).
Wo kommt aber nun das "self" her?
Dies ist ein Parameter, der beim Aufruf einer Methode mit übergeben wird. Da der Inhalt dieses Parameters aber festliegt, darf man dessen Wert nicht angeben können.
Intern sieht der Aufruf der Methode so aus:
Delphi-Quellcode:
MachWas(self,Sender);
Es wird also nicht einer, sondern es werden zwei Parameter übergeben.

Das hat jetzt für das konkrete Beispiel folgenden Effekt:
MachWas ist keine Methode, und hat somit keinen unsichtbaren Parameter self. Somit wird dem ersten Parameter der Wert von Self, der jetzt = nil ist, übergeben.
Gönnt man jetzt der Prozedur einen weiteren Parameter, stimmt die Struktur wieder, und es funktioniert wie erwartet.

Dieses Konstruktion
Delphi-Quellcode:
@radiogroup.OnClick := @machwas;
hat nur den Zweck den Compiler auszutricksen, damit er nicht erkennt, dass keine Methode übergeben wird.

APP 25. Okt 2003 16:32

Re: prozedur aufruf und sender
 
Hallo Christian,

Danke für Deine Ausführungen,

Zitat:

Nun kannst Du aber in der Methode auch noch mit Hilfe von self auf die Eigenschaften und Methoden der Klasse zugreifen
das war mir soweit klar.

Ich habe bis jetzt, wenn ich einem Ereignis eine Prozedur zuordnen wollte immer
eine Prozedur geschrieben, die die gleichen Parameter hat wie das Ereignis.

Ah, jetzt ist der Groschen gefallen:

Du hast Messerscharf geschlossen, dass

Zitat:

procedure machwas(sender : TObject); // das ist eine Methode
...
var radiogroup : TRadiogroup;
...
radiogroup := TRadioGroup.Create(panel);
radiogroup.Parent := Pnl_eingabe;
@radiogroup.OnClick := @machwas;
...
procedure machwas(sender : TObject); // das ist eine Prozedur
begin
if sender = radiogroup then
showmessage('radiogroup geklickt');
end;
Und da LoL in einer Methode eine Komponente erzeugt und dessen Ereignis einer Prozedur
mit dem Namen der Methode zuweist, gibt es das Problem mit dem versteckten Self,... NEIN,
JETZT KLEMMT ES WIEDER :freak: :freak:

LoL weist einem Ereignis eine Prozedur zu, das geht doch auch ohne Zusatzparameter, oder?
Andererseits, @machwas bezieht sich auf die Methode, oder?
Wie kann er dann auch noch bei der gleichnamigen Prozedur, die mit der Methode nichts zu tun hat
auf Radiogroup abfragen. (Ich dachte ausserdem beim Sender ist nur IS oder AS erlaubt)

Fragen über Fragen, ich weiß, aber ich möchte das Verstehen und etwas dazulernen. :)

p.s.
Deine Erklärung habe ich schon verstanden, das mit dem versteckten Sender kam auch
wieder aus den Tiefen meines Gerhirns hoch, nachdem Du es erwähnt hattest, (Dinge die
selbstverständlich benutzt werden, vergesse ich allzuleicht) aber es gibt einen Unterschied zw.
Deinem und LoLs Code.

Christian Seehase 25. Okt 2003 19:33

Re: prozedur aufruf und sender
 
Moin Armin,

der Knackpunkt ist, dass die Prozedur einer Eigenschaft zugewiesen ist, die die Adresse einer Methode erwartet (in diesem Falle vom Typ TNotifyEvent). Dadurch geht der Compiler davon aus, dass die Adresse in der Eigenschaft die einer Methode ist, und übergibt beim Aufruf zwei Parameter. Wenn der Compiler auf die Deklaration Prozedur trifft, "weiss" er nichts davon, dass diese später als Methode aufgerufen wird, und erzeugt den Code wie es bei einer Prozedur üblich ist.
Das die Zuweisung einer Prozeduradresse erfolgt ist, ist ja nur dem Trick mit den @ zu verdanken. Ohne @ würde der Compiler das ja gar nicht zulassen. Deklariert man jetzt die Prozedur so, dass die Parameteranzahl passt funktioniert es anschliessend wie erwartet, es sieht nur unüblich aus.
Wenn man es genau betrachet, funktioniert der Trick auch nur, weil Borland darauf verzichtet hat für die Zuweisung von Ereignissen eine Set Methode einzubauen.

APP 25. Okt 2003 19:42

Re: prozedur aufruf und sender
 
Hallo Christian,
Zitat:

die Prozedur einer Eigenschaft zugewiesen ist, die die Adresse einer Methode erwartet
meinst Du nun da das @xx := @yy Konstrukt?

Verzeih meine Begriffstutzigkeit, es kann sein, das ich jetzt total
im falschen Eck bin, aber ich riskiere es trotzdem:

Folgendes funktioniert bei mir:

Delphi-Quellcode:
PROCEDURE TForm1.Button5Click(Sender: TObject);
VAR
   radiogroup                     : TRadiogroup;
BEGIN
   radiogroup := TRadioGroup.Create(self);
   radiogroup.Parent := self;
   radiogroup.OnClick := machwas;
   radiogroup.Items.Add('a');
END;

PROCEDURE TForm1.machwas(sender: TObject);
BEGIN
   IF (Sender IS TRadiogroup) THEN
      showmessage('radiogroup geklickt');
END;

Christian Seehase 25. Okt 2003 19:59

Re: prozedur aufruf und sender
 
Moin Armin,

das funktioniert, weil in dem Falle MachWas eine Methode von TForm1, und von der Deklaration her gültig ist. Z.B. ein MouseDown Event wäre nicht gegangen.
Hättest Du MachWas so deklariert:
Delphi-Quellcode:
procedure MachWas(Sender: TObject);
begin
  //...
end;
hättest Du es so zuweisen müssen
Delphi-Quellcode:
@radiogroup.OnClick := @machwas;
da es der Compiler schon nicht anders akzeptiert hätte.
Nur würde es nicht funktionieren, da das was in der Prozedur als Parameter Sender übergeben wird, der Wert von Self ist.

Würde man jetzt MachWas so deklarieren
Delphi-Quellcode:
procedure MachWas(ASelf: TComponent;Sender: TObject);
begin
  //...
end;
Müsste man es zwar so
Delphi-Quellcode:
@radiogroup.OnClick := @machwas;
zuweisen, damit der Compiler es akzeptiert, aber es würde funktionieren.
Jetzt wäre beim Aufruf ASelf = nil (vermutlich, dass es tatsächlich nil ist weiss ich nicht sicher) und Sender gleich der Komponente, die das Ereignis ausgelöst hat, also in diesem Falle radiogroup.

APP 25. Okt 2003 20:15

Re: prozedur aufruf und sender
 
Danke Christian, jetzt habe ich es begriffen! :love:


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:05 Uhr.
Seite 1 von 2  1 2      

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