Prozedur einem Event zuordnen

Hallo,
ich weiß einfach nicht mehr weiter. Die Folgenden beiden Programme sind auf die gleiche weise aufgebaut, aber komischerweise kann ich nur das erstere compilieren.

Das erste Programm löst beim öffnen eines Sockets ein OnListen-Event aus. Dieses Event wird mit der Zeile „@S.OnListen := @SocketNotifyEvent;“ an die entsprechende Prozedur gebunden, die beim Ausführen des Programms auch ordungsgemäß ausgeführt wird.

Das zweite Programm soll alle 200 ms ein OnTimer-Event auslösen. Wie im ersten Programm möchte ich die entsprechende Prozedur „NotifyEvent(Sender: TObject);“ mit der Zeile „@T.OnTimer := @NotifyEvent;“ an dieses Event binden. Leider will der Compiler das jedoch so nicht hinnehmen und meldet mir den Fehler: „Inkompatible Typen: ‚TNotifyEvent‘ und ‚Pointer‘“.

Ich verstehe das nicht. Was mache ich falsch?

Ps: Das Programm soll auf jeden Fall als reines Konsolenprogramm ohne Fenster laufen. Daher muss ich auch die Events über den Programmcode zuordnen und kann nicht den Objektinspector verwenden :frowning:

Programm 1

program Project1;
{$APPTYPE CONSOLE}
uses
 sysutils,
 scktcomp;

var S : TServerSocket;

procedure SocketNotifyEvent(Sender: TObject; Socket: TCustomWinSocket);
begin
 WriteLn('Yes');
 Readln;
end;

begin
 S := TServerSocket.Create(Nil);
 Try
 @S.OnListen := @SocketNotifyEvent;
 S.Open; // -\> Active:=True; -\> löst das OnListen-Event aus
 Writeln('Weiter mit Enter');
 Readln;
 Finally
 S.Free;
end;

end.

Programm 2

program TimeEvent;
{$APPTYPE CONSOLE}
uses
 SysUtils,
 ExtCtrls;

var
 T : TTimer;
 i : Integer;

procedure NotifyEvent(Sender: TObject);
begin
 writeln('yes');
 beep;
end;

begin
 T := TTimer.Create(nil);
 T.Interval := 200; // -\> löst alle 200 ms das OnTimer-Event aus
 try
 @T.OnTimer := @NotifyEvent; { [Fehler]: Inkompatible Typen: 'TNotifyEvent' und 'Pointer' }
 T.Enabled := true; // aktiviert den Timer
 writeln('Warte auf Event: ');
 for i := 1 to 5 do begin
 sleep(100);
 writeln('warte ' + inttostr(i\*100) + 'ms...');
 end;
 T.Enabled := false; // deaktiviert den Timer
 finally
 T.Free;
end;

end.

Hallo,

Ich kenne den TSocketServer nicht. Wenn das aber ein Konventions-konformer Typ ist, wundere ich mich, daß die Zuweisung hier funktioniert.

Bei TTimer bin ich mir sicher, zu wissen, warum das so nicht geht: TTimer.OnTimer erwartet ein TNotifyEvent, und das ist die Einsprungaddresse für eine Methode (mit einem Argument vom Typ TObject). Du versuchst aber, die Addresse einer Prozedur zu übergeben. Intern besteht der Methodenzeiger aus zwei(!) Zeigern, während der Zeiger auf eine Prozedur nur ein einfacher Zeiger ist. Daher die Fehlermeldung.

Der einzige mir bekannte Weg, das zu lösen, ist, deine Prozedur „NotifyEvent“ als Methode eines Objekts zu deklarieren. Hier würde sich in deinem Fall anbieten, von TSocketServer eine Klasse abzuleiten (nennen wir sie TSocketServer2), welche NotifyEvent als Methode enthält:

 type
 TSocketServer2 = class(TSocketServer)
 Procedure NotifyEvent(Sender:TObject);
 end;
...
procedure TSocketServer2.NotifyEvent(Sender:TObject);
begin
 writeln('yes');
 beep;
end;
...
 T.OnTimer := TSocketServer.NotifyEvent;
...

Alles klar?

Gruß,
Jochen

Alles klar?

Gruß,
Jochen

hmm, dann verwende ich also TSocketServer, um auf ein Event von TTimer zu reagieren. Das ist ja irgendwie komisch. Das muß doch auch ohne diesen Umweg gehen.

Aber danke erst mal für die Antwort.
Das mit den zwei Zeigern wusste ich nämlich noch nicht.

Gruß
Veit

Hallo Veit,

hmm, dann verwende ich also TSocketServer, um auf ein Event
von TTimer zu reagieren.

Es muß nicht TSocketServer sein. Es ein beliebiges Objekt sein. Du kannst auch eine eigene TTimer-Klasse ableiten, die diese TSocketServer-Sache macht. Viele Wege fürhren nach Rom - schnelle, schöne, einfache, schwere, langsame, …

Gruß
Jochen