![]() |
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:
warum sagt der dann das bei aufruf der prozedur "machwas" der sender nil ist?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; |
Re: prozedur aufruf und sender
Hallo Christoph,
Delphi-Quellcode:
RadioGroup.OnClick := machwas;
Delphi-Quellcode:
sollte es heißen.
WITH (Sender AS Tradiogroup) DO
showmessage('radiogroup geklickt'); |
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:
Du hast immer self ausgelesen.
procedure machwas(oSelf : TComponent;Sender : TObject);
Da es sich aber um eine Prozedur, und nicht um eine Methode handelt, ist self = nil. |
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:
so noch nie gearbeitet habe, und die Zeigeroperation
@radiogroup.OnClick := @machwas;
"@machwas" liefert offensichtlich den Eintrittspunkt von "machwas". Hast Du nun daraus geschlossen, dass Christoph noch einen Parameter mitgeben muß? Ansonsten sollte ja
Delphi-Quellcode:
ausreichend sein, oder?
RadioGroup.OnClick := machwas;
|
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:
Auf den ersten Blick sehen die gleich aus.
// Methode:
procedure TIrgendeineKlasse.MachWas(Sender: TObject); begin ShowMessage('HALLO'); end; // Prozedur procedure MachWas(Sender: TObject); begin ShowMessage('HALLO'); end; 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:
Es wird also nicht einer, sondern es werden zwei Parameter übergeben.
MachWas(self,Sender);
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:
hat nur den Zweck den Compiler auszutricksen, damit er nicht erkennt, dass keine Methode übergeben wird.
@radiogroup.OnClick := @machwas;
|
Re: prozedur aufruf und sender
Hallo Christian,
Danke für Deine Ausführungen, Zitat:
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:
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. |
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. |
Re: prozedur aufruf und sender
Hallo Christian,
Zitat:
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; |
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:
hättest Du es so zuweisen müssen
procedure MachWas(Sender: TObject);
begin //... end;
Delphi-Quellcode:
da es der Compiler schon nicht anders akzeptiert hätte.
@radiogroup.OnClick := @machwas;
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:
Müsste man es zwar so
procedure MachWas(ASelf: TComponent;Sender: TObject);
begin //... end;
Delphi-Quellcode:
zuweisen, damit der Compiler es akzeptiert, aber es würde funktionieren.
@radiogroup.OnClick := @machwas;
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. |
Re: prozedur aufruf und sender
Danke Christian, jetzt habe ich es begriffen! :love:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:44 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz