Autor Beitrag
turngrobi
Hält's aus hier
Beiträge: 7

WIN 2000
D6 Prof, D7 Prof
BeitragVerfasst: 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
ausblenden 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; // -> Active:=True; -> löst das OnListen-Event aus
  Writeln('Weiter mit Enter');
  Readln;
  Finally
  S.Free;
end;

end.

Programm 2
ausblenden volle Höhe 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:
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; // -> 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.


Moderiert von user profile iconTino: Code- durch Delphi-Tags ersetzt.
CenBells
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1547

Win 7
Delphi XE5 Pro
BeitragVerfasst: Mi 26.11.03 13:51 
hallo,

Du machst
ausblenden Delphi-Quelltext
1:
 @T.OnTimer := @NotifyEvent;					


probier es so
ausblenden Delphi-Quelltext
1:
 @(T.OnTimer) := @NotifyEvent;					

Gruß
Ken

_________________
Eine Klasse beschreibt die Struktur und das Verhalten einer Menge gleichartiger Objekte.
ErnestoChe
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: Mi 26.11.03 14:08 
Hi,

wie wärs, wenn man das einfach so macht:

ausblenden Delphi-Quelltext
1:
T.OnTimer := NotifyEvent;					


MFG

- Ernesto -
CenBells
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1547

Win 7
Delphi XE5 Pro
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Do 27.11.03 09:42 
Und es geht doch:
ausblenden volle Höhe 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:
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; // -> löst alle 200 ms das OnTimer-Event aus 
  try 
    p.pMethod := @NotifyEvent;
    p.pObject := nil;
    T.OnTimer := TNotifyEvent(p);

    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;

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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1547

Win 7
Delphi XE5 Pro
BeitragVerfasst: Do 27.11.03 10:33 
@motzi,

ja das es wohl mit Pointer klimbim (heute mein lieblingswort) klappt ist klar. :wink:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: 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 :oops:), 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: 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:

ausblenden 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; // -> löst alle 200 ms das OnTimer-Event aus
  try
    p.pMethod := @NotifyEvent;
    p.pObject := nil;
    T.OnTimer := TNotifyEvent(p);

    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...');
      Application.ProcessMessages;                      // <----------
    end;
    T.Enabled := False;
  finally
    T.Free;
  end;
end.


MFG

- Ernesto -
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: 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:

ausblenden volle Höhe 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:
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; // -> löst alle 200 ms das OnTimer-Event aus
  try
    p.pMethod := @NotifyEvent;
    p.pObject := nil;
    T.OnTimer := TNotifyEvent(p);

    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...');
      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 Threadstarter
Hält's aus hier
Beiträge: 7

WIN 2000
D6 Prof, D7 Prof
BeitragVerfasst: Fr 28.11.03 15:32 
jau, super, ihr seid genial. das funktioniert.
Das hätte ich nie herausgefunden.

Danke
maximus
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 896

Win XP, Suse 8.1
Delphi 4/7/8 alles prof
BeitragVerfasst: 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:

ausblenden 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 user profile iconTino: Beitrag aus DP direkt eingefügt.

_________________
mfg.
mâximôv
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 09.12.03 18:34 
@Motzi: Irgendwie haut das aber noch nicht so ganz hin:
ausblenden volle Höhe 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:
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; // -> löst alle 200 ms das OnTimer-Event aus
  try
    p.pMethod := @NotifyEvent;
    p.pObject := nil;
    T.OnTimer := NotifyEvent(p);  // [Fehler] Project2.dpr(32): Inkompatible Typen: 'TObject' und 'TMethodPointer'

    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.

[/code]
obbschtkuche
Gast
Erhaltene Danke: 1



BeitragVerfasst: Di 09.12.03 18:43 
Es hat ein T gefehlt:

ausblenden volle Höhe 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:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
program Project2;

{$APPTYPE CONSOLE} 

uses
  SysUtils, ExtCtrls, Classes; // <- dazu

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; // -> löst alle 200 ms das OnTimer-Event aus 
  try 
    p.pMethod := @NotifyEvent; 
    p.pObject := nil; 
    T.OnTimer := TNotifyEvent(p); // <-- "T" dazu

    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.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: 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



BeitragVerfasst: Di 09.12.03 19:04 
Versehentlich die Classes.dcu überschrieben, was? :roll:
TNotifyEvent ist hier ein Typecast und keine Procedure...
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 09.12.03 19:10 
Ach menno. Ich habe übersehen, dass man noch classes.pas braucht. Jetzt geht alles. Danke.