| Autor |
Beitrag |
turngrobi
Hält's aus hier
Beiträge: 7
WIN 2000
D6 Prof, D7 Prof
|
Verfasst: Mi 26.11.03 13:14
Hallo,
ich weiß einfach nicht mehr weiter. Die Folgenden beiden Mini-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 :(
Programm 1
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| 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; Writeln('Weiter mit Enter'); Readln; Finally S.Free; end;
end. |
Programm 2
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| 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; try @T.OnTimer := @NotifyEvent; T.Enabled := true; writeln('Warte auf Event: '); for i := 1 to 5 do begin sleep(100); writeln('warte ' + inttostr(i*100) + 'ms...'); end; T.Enabled := false; finally T.Free; end;
end. |
Moderiert von Tino: Code- durch Delphi-Tags ersetzt.
|
|
CenBells
      
Beiträge: 1547
Win 7
Delphi XE5 Pro
|
Verfasst: Mi 26.11.03 13:51
hallo,
Du machst
Delphi-Quelltext 1:
| @T.OnTimer := @NotifyEvent; |
probier es so
Delphi-Quelltext 1:
| @(T.OnTimer) := @NotifyEvent; |
Gruß
Ken
_________________ Eine Klasse beschreibt die Struktur und das Verhalten einer Menge gleichartiger Objekte.
|
|
ErnestoChe
      
Beiträge: 528
Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
|
Verfasst: Mi 26.11.03 14:08
Hi,
wie wärs, wenn man das einfach so macht:
Delphi-Quelltext 1:
| T.OnTimer := NotifyEvent; |
MFG
- Ernesto -
|
|
CenBells
      
Beiträge: 1547
Win 7
Delphi XE5 Pro
|
Verfasst: Mi 26.11.03 15:24
@ErnetoChe: das wird nicht klappen, da die Prozedur NotifyEvent keine Prozedur eines Objekts ist und daher lässt die sich nicht standartmäßig zuweisen.
Gruß
Ken
_________________ Eine Klasse beschreibt die Struktur und das Verhalten einer Menge gleichartiger Objekte.
|
|
ErnestoChe
      
Beiträge: 528
Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
|
Verfasst: Mi 26.11.03 16:56
Hi,
Uups, stimmt. Ich hätte den Thread genauer durchlesen sollen. Dein Ansatz wird aber auch nicht funktionieren, da ein TNotifyevent erwartet wird.
Hier ist im vorletzten Posting eine Lösung, wie man einen Timer in eine Konsolen-Anwendung implementieren kann.
MFG
- Ernesto -
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Do 27.11.03 09:42
Und es geht doch:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
| type PMethodPointer = ^TMethodPointer; TMethodPointer = packed record pMethod: Pointer; pObject: TObject; end;
var p: TMethodPointer;
procedure NotifyEvent(Self: TObject; Sender: TObject); begin writeln('yes'); beep; end;
begin T := TTimer.Create(nil); T.Interval := 200; try p.pMethod := @NotifyEvent; p.pObject := nil; T.OnTimer := TNotifyEvent(p);
T.Enabled := true; writeln('Warte auf Event: '); for i := 1 to 5 do begin sleep(100); writeln('warte ' + inttostr(i*100) + 'ms...'); end; T.Enabled := false; finally T.Free; end; |
Siehe auch: www.delphipraxis.net/topic9618,15.html
Edit: Korrektur - Self-Pointer hinzugefügt (siehe mein nächstes Posting)
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Zuletzt bearbeitet von Motzi am Do 27.11.03 11:25, insgesamt 1-mal bearbeitet
|
|
CenBells
      
Beiträge: 1547
Win 7
Delphi XE5 Pro
|
Verfasst: Do 27.11.03 10:33
@motzi,
ja das es wohl mit Pointer klimbim (heute mein lieblingswort) klappt ist klar.
Es war ja auch nur darauf bezogen, was ErnestoChe meinte *G*
Gruß
Ken
_________________ Eine Klasse beschreibt die Struktur und das Verhalten einer Menge gleichartiger Objekte.
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Do 27.11.03 11:25
Meine Methode basiert einfach auf der Tatsache, dass Methodenzeiger eigentlich 2 Pointer sind - einerseits der Zeiger auf die Funktion/Prozedur und andrerseits der Zeiger auf das Objekt auf das sich die Methode bezieht. Wichtig ist aber (und da fallt mir gerade auf, dass ich das in obigem Beispiel vergessen hab  ), dass die Funktion noch den sonst versteckten Parameter "Self" extra beinhalten muss. Dieser Parameter wird von Delphi sonst immer versteckt mitgeführt (EAX-Register), muss also in einer normalen Prozedur auch eingeführt werden, wenn man diese einem Methodenzeiger zuweisen will, damit die Parameterreihenfolge nicht durcheinander kommt! -> Hab meinen obigen Beitrag entsprechend editiert...
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
ErnestoChe
      
Beiträge: 528
Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
|
Verfasst: Do 27.11.03 12:04
Hi,
klar, so gehts natürlich auch. Es fehlt jedoch noch was. Damit sich auch was tut und das von turngrobi gewünschte Ergebnis eintritt, sollte man ein Application.ProcessMessages in die Schleife mit reinnehmen, und damit das überhaupt geht die Unit Forms noch in die uses aufnehmen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| uses SysUtils, ExtCtrls, Classes, Forms;
begin T := TTimer.Create(nil); T.Interval := 200; try p.pMethod := @NotifyEvent; p.pObject := nil; T.OnTimer := TNotifyEvent(p);
T.Enabled := True; Writeln('Warte auf Event: '); for i := 1 to 5 do begin Sleep(100); Writeln('warte ' + IntToStr(i * 100) + 'ms...'); Application.ProcessMessages; end; T.Enabled := False; finally T.Free; end; end. |
MFG
- Ernesto -
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Do 27.11.03 12:57
Ja, natürlich, da ja sonst nicht die Message-Queue abgearbeitet wird! Allerdings würd ich hier auf das TApplication-Objekt verzichten und stattdessen lieber auf die nonVCL-Variante zurückgreifen - Luckie hat sie hier im Forum sicher schonmal gepostet!
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
ErnestoChe
      
Beiträge: 528
Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
|
Verfasst: Do 27.11.03 14:56
Hi,
klar, kann man machen. Da ich hier im Forum keine nonVcl-Variante gefunden habe, poste ich sie mal:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| uses Windows;
procedure MyProcessMessage; var msg: TMSG; begin if PeekMessage(msg, 0, 0, 0, PM_REMOVE) then begin TranslateMessage(msg); DispatchMessage(msg); end; end;
begin T := TTimer.Create(nil); T.Interval := 200; try p.pMethod := @NotifyEvent; p.pObject := nil; T.OnTimer := TNotifyEvent(p);
T.Enabled := True; Writeln('Warte auf Event: '); for i := 1 to 5 do begin Sleep(100); Writeln('warte ' + IntToStr(i * 100) + 'ms...'); MyProcessMessage; end; T.Enabled := False; finally T.Free; end; end. |
Application.ProcessMessages macht eigentlich auch nichts anderes, als mit PeekMessage in die Nachrichten-Queue zu schauen. So spart man sich halt das Application-Object und damit die unit Forms.
MFG
- Ernesto -
Zuletzt bearbeitet von ErnestoChe am Fr 28.11.03 15:36, insgesamt 1-mal bearbeitet
|
|
turngrobi 
Hält's aus hier
Beiträge: 7
WIN 2000
D6 Prof, D7 Prof
|
Verfasst: Fr 28.11.03 15:32
jau, super, ihr seid genial. das funktioniert.
Das hätte ich nie herausgefunden.
Danke
|
|
maximus
      
Beiträge: 896
Win XP, Suse 8.1
Delphi 4/7/8 alles prof
|
Verfasst: Fr 28.11.03 16:16
Noch einfacher wäre eine class methode, da spart man sich das pointer-gelöt, hat aber dafür eine kleine klasse mehr:
| maximov hat folgendes geschrieben: | Aha...
Das liegt wohl daran, dass alle gängigen events methoden erwarten und keine normalen prozeduren. Also procedure (sender:TObject) of object;. Du kannst das mit class methoden umgehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| ... TWrapper = class class procedure TuWas(sender:TObject); end; ... procedure TWrapper.TuWas(Sender: TObject); begin ShowMessage('Ich tu was'); end;
var SubMenu: TMenuItem;
procedure InstalliereWas(MainMenu: TMainMenu); begin ... SubMenu.OnClick:=TWrapper.TuWas; |
mfg maximom |
nur zur ergänzung.
mfg.
Moderiert von Tino: Beitrag aus DP direkt eingefügt.
_________________ mfg.
mâximôv
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 09.12.03 18:34
@Motzi: Irgendwie haut das aber noch nicht so ganz hin:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| program Project2;
{$APPTYPE CONSOLE}
uses SysUtils, ExtCtrls;
type PMethodPointer = ^TMethodPointer; TMethodPointer = packed record pMethod: Pointer; pObject: TObject; end;
var T: TTimer; p: TMethodPointer; i: Integer;
procedure NotifyEvent(Self: TObject; Sender: TObject); begin writeln('yes'); beep; end;
begin T := TTimer.Create(nil); T.Interval := 200; try p.pMethod := @NotifyEvent; p.pObject := nil; T.OnTimer := NotifyEvent(p); T.Enabled := true; writeln('Warte auf Event: '); for i := 1 to 5 do begin sleep(100); writeln('warte ' + inttostr(i*100) + 'ms...'); end; T.Enabled := false; finally T.Free; end; end. |
[/code]
|
|
obbschtkuche
Gast
Erhaltene Danke: 1
|
Verfasst: Di 09.12.03 18:43
Es hat ein T gefehlt:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| program Project2;
{$APPTYPE CONSOLE}
uses SysUtils, ExtCtrls, Classes; type PMethodPointer = ^TMethodPointer; TMethodPointer = packed record pMethod: Pointer; pObject: TObject; end;
var T: TTimer; p: TMethodPointer; i: Integer;
procedure NotifyEvent(Self: TObject; Sender: TObject); begin writeln('yes'); beep; end;
begin T := TTimer.Create(nil); T.Interval := 200; try p.pMethod := @NotifyEvent; p.pObject := nil; T.OnTimer := TNotifyEvent(p); T.Enabled := true; writeln('Warte auf Event: '); for i := 1 to 5 do begin sleep(100); writeln('warte ' + inttostr(i*100) + 'ms...'); end; T.Enabled := false; finally T.Free; end; end. |
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 09.12.03 18:54
Nein. Jetzt bekomme ich:
| Zitat: |
[Fehler] Project2.dpr(32): Undefinierter Bezeichner: 'TNotifyEvent'
|
Was auch logisch ist, da es keine Prozedur mit dem Namen TNotifyEvent gibt.
|
|
obbschtkuche
Gast
Erhaltene Danke: 1
|
Verfasst: Di 09.12.03 19:04
Versehentlich die Classes.dcu überschrieben, was?
TNotifyEvent ist hier ein Typecast und keine Procedure...
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 09.12.03 19:10
Ach menno. Ich habe übersehen, dass man noch classes.pas braucht. Jetzt geht alles. Danke.
|
|