Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - createn und destroyen eines timer objekts zur laufzeit


Green - Do 11.05.06 23:13
Titel: createn und destroyen eines timer objekts zur laufzeit
wie der titel schon sagt, ich will einen timer zur laufzeit createn der nach x sekunden abc() und def() macht, also programmierbar ist, der dannach sich selbst per destroy zerstört, alles schön OOP, aber wie mach ich das???

mfG Green


Narses - Do 11.05.06 23:36

Moin!


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var
  Timer: TTimer;

Timer := TTimer.Create(NIL);

FreeAndNil(Timer);

cu
Narses


Green - Fr 12.05.06 07:37

ääähm, jo und wo setz ich jetzt die proceduren die durchführen soll? also das was er letztendlich timen soll?


Jakob Schöttl - Fr 12.05.06 07:55
Titel: re
Ereignisse sind Eigenschaften.
Ereignisse sind Methodenzeiger.
...
(Quelle: EntwicklerHandbuch, 5 cm dick)

Ein ereignis kann man so deklarieren:

Delphi-Quelltext
1:
  OnTimer: procedure(Sender:TObject);                    


Das Ereignis OnTimer musst du natürlich nicht selber deklarieren, du musst diesem Ereigniss aber eine Methode (Eine Procedure mit den selben Parametern) zuweisen. Das machst du dann so

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var  
  Timer: TTimer;  

 
  Timer := TTimer.Create(NIL);  
  Timer.OnTimer := DeineProcedure;  { Deine Procedure muss die erforderten Parameter
(Sender: tObject) haben. Bei der zuweisung brauchst du diese aber nicht anzugeben. In der
Procedure kann dann stehen was will, also abc() und def(). }

 
  FreeAndNil(Timer);


DeineProcedure deklarierst du im Public- oder Privat-Abschnitt von TForm und implementierst sie unten.


Green - Sa 13.05.06 07:52

ok vielen dank, das hab ich kapiert.

aber noch ne frage: was mach ich wenn ich jetzt erstens dynamisch timer erstellen will also die timer dynamisch benennnen will:
timer1 timer2 timer3

wobei die zahl halt inner variable ist, und wie greif ich jetzt dynamisch, das heisst wieder mit der variable auf den timerx zu?
desweiteren kriege ich beim zuweisen immer die fehlermeldung:
Zitat:
[Error] Unit1.pas(25): Undeclared identifier: 'TTimer'


meine uses sind:
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

und ich arbeite mit D6 Enterprise
mfG Green


Horst_H - Sa 13.05.06 09:02

Hallo,

aus Turbo-Pascal Zeiten:
Nimm einen Timer mit kuerzeren Intervallen(20 ms ist unter Windows das Minimum) und merke Dir mit einem Zaehler, wer gerade dran ist.
Ein

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
TprcTimer= procedure(???Was Du glaubst, zu brauchen);
record MyTime =
        MomT,
        StartT : integer;
        prcTime : TprocTime;
      end;

Dann erzeugst du eben ein dynamische Feld aTimer : array of Mytime.
Deine ontimer Procedure klappert jetzt alle Feldelemente ab.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure ontimer(..)
var 
  i : integer;
begin
  for i := 0 to High[aTimer] do
    with aTimer[i] do
      begin
      MomT := MomT-timer.interval;
      If MomT< 0 then 
         begin
         MomT := MomT+StartT;//MomT := StartT;
        prcTime;
        end;
      end;
end;


Gruss Horst


Gausi - Sa 13.05.06 09:07

Für den Timer musst du ExtCtrls mit einbinden, wie ein schneller Blick in die Delphi-Hilfe verrät ;-)


Green - Sa 13.05.06 09:15

@horst_h
öööh das blick ich jetzt nit ganz, aber ich werd den tip von

@Gausi
zu herzen nehmen... danke erstmal vielmals, mfG Green

eine weitere frage: bei dem

Delphi-Quelltext
1:
2:
3:
  Timer.OnTimer := DeineProcedure;  { Deine Procedure muss die erforderten Parameter
(Sender: tObject) haben. Bei der zuweisung brauchst du diese aber nicht anzugeben. In der
Procedure kann dann stehen was will, also abc() und def(). }


ich hab jetzt meine procedure aber ich will ausser Sender: TObject noch was übergeben... aber wie mach ich das?
also wenn ich das so schreib:

Delphi-Quelltext
1:
2:
3:
procedure showit(x: integer; Sender: TObject);
//und dann
Timerarray[x].OnTimer := showit(x,Button1);

dann krieg ich immer nen fehler...
Zitat:

[Error] Unit1.pas(36): Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'


mfG Green


MrSaint - Sa 13.05.06 10:21

So einfach ist das nicht möglich.- Ich würde eine Klasse von TTimer ableiten, der eine weitere Property geben (z.B. "Button") und die dann vor der Zuweisung der Procedure setzen. Dann kannst du in der Procedure per TMyTime(Sender).Button auf den Button zugreifen.


MrSaint


Green - Sa 13.05.06 10:51

ich habs: ich benutz einfach die Property 'Tag' die is genau für sowas gedacht...

Zitat:
Stores an integer value as part of a component.

property Tag: Longint;

Description

Tag has no predefined meaning. The Tag property is provided for the convenience of developers. It can be used for storing an additional integer value or it can be typecast to any 32-bit value such as a component reference or a pointer.


aber danke für die idee, wäre ich ohne dich nit draufgekommen :)

mfG Green


Green - Sa 13.05.06 11:00

oops, mir fällt grade auf das ich da nen denkfehler gemacht hab...

wenn ich im Timer<x> tag auf x setz ums in der procedure von OnTimer abzufragen, dann brauch ich ja in der Procedure auch die nummer des timers in der x steht, aber des müsste ich ja mit übergeben wenn ich ONTimer setz was ja leider nicht geht. kann es sein das das unmöglich ist? mein problem ist halt das ich eben den timer setzen will beispielsweise auf 5 sekunden und der dann was bestimmtes machen soll ( abc() def() ) und sich dann per FreeAndNil(Timer); selber beenden soll da er ja nicht unendlich mal abc un def machen soll sondern nur einmal, bzw. halt eine orgeschribene anzahl... dazu brauch ich aber die nummer des timers, welche ich ja dummerweise nicht hab... kann mir jemand helfen? bzw. hat jemand das problem kapiert?

es muss doch möglich sein das objekt das mir die procedure aufgerufen hat herauszufinden... so neben bei: was bringt sender eigentlich?

mfG Green


MrSaint - Sa 13.05.06 11:12

user profile iconMrSaint hat folgendes geschrieben:
Dann kannst du in der Procedure per TMyTime(Sender).Button auf den Button zugreifen.


Green - Sa 13.05.06 11:20

oh yeah ENDLICH GEHTS!!! Vielen Dank 8) ihr seid super

mfG Green


Green - Sa 13.05.06 11:31

äähm noch ne frage... :oops:
nach dem FreeAndNil(Timer); wie sieht denn Timer (also die variable) dann aus? also kann ich rausfinden ob ich den timer schon gekillt hab?

mfG Green


Narses - Sa 13.05.06 11:42

Moin!

FreeAndNil eingeben, Cursor draufstellen und F1 drücken, dann lesen... ;)

cu
Narses


Blackheart666 - Sa 13.05.06 11:53

Vieleicht hilft dir das aus der Delphi Ecke

// Hier die effizienteste Methode mal schnell einen Timer zu erzeugen
// und wieder zu entfernen. Wenn auf diese Art gleichzeitig mehrere Timer
// erzeugt werden sollen, muss TimerId hochgezählt werden.

// Getestet mit D4 unter Win98



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
const TimerID: Integer = 1// muss größer als Null sein 
 
procedure OnTimer; 
begin 
  killtimer(application.handle, TimerID); 
  beep; 
  showmessage('Zeit ist abgelaufen'); 
end
 
procedure TForm1.Button1Click(Sender: TObject); 
var zeit: cardinal; 
begin 
  zeit := 1000// Millisekunden 
  settimer(application.handle, TimerID, zeit, @OnTimer); 
end;


Horst_H - Sa 13.05.06 13:18

Hallo,

damit man mal >sieht< was ich meinte.
Es n Rechtecke,Ellipsen auf die Form.convas gezeichnet und blinken vor sich hin.
Bei n = 4000 ist die Belastung < 1 %.
Gruss Horst


Jakob Schöttl - So 14.05.06 18:35
Titel: ?
user profile iconHorst_H hat folgendes geschrieben:
Hallo,

TprcTimer= procedure(???Was Du glaubst, zu brauchen);
record MyTime =
MomT,
StartT : integer;
prcTime : TprocTime;
end;
`

@Horst_H: Kann es sein, dass du dich da vertan hast? Wir sind doch nicht bei C++!
Record-Typen deklariert man bei pascal so:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
type
  MyTime = record
    MomT,
    StartT : integer;
    prcTime : TprocTime;
  end;


-Pl- - Do 25.01.07 01:40
Titel: Re: re
user profile iconJakob Schöttl hat folgendes geschrieben:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var  
  Timer: TTimer;  

 
  Timer := TTimer.Create(NIL);  
  Timer.OnTimer := DeineProcedure;  { Deine Procedure muss die erforderten Parameter
(Sender: tObject) haben. Bei der zuweisung brauchst du diese aber nicht anzugeben. In der
Procedure kann dann stehen was will, also abc() und def(). }

 
  FreeAndNil(Timer);



Ich habe es genau so gemacht, aber es kommt trotzdem der Fehler:
[Fehler] : Inkompatible Typen: 'Methodenzeiger und reguläre Prozedur'
für folgende Zeile:

Delphi-Quelltext
1:
DrawTimer.OnTimer := DrawTimerTimer;                    


Das weitere sieht so aus:

Delphi-Quelltext
1:
procedure DrawTimerTimer(Sender: TObject);                    



Delphi-Quelltext
1:
2:
3:
4:
procedure DrawTimerTimer(Sender: TObject);
begin
  Draw;
end;


Das müssten die interessanten Abschnitte sein ... bin ich einfach nur blind und hab was übersehen oder wo liegt der Fehler ?

Vielen Dank für eure Hilfe !

ps: Ich weiss das der Thread ziemlich weit ausgegraben ist *Suchfunktion tätschel*


Narses - Do 25.01.07 01:52

Moin!

Mach deine DrawTimerTimer-Prozedur zu einem Mitglied deiner Formualklasse, dann klappt das (sagt doch auch der Compiler). ;)

cu
Narses


-Pl- - Do 25.01.07 01:57

Macht sich in einer eignen Unit ohne Form irgendwie schlecht ... :(


Narses - Do 25.01.07 01:59

Moin!

Dann mach eine Dummy-Klasse um die Methode drum rum. ;)

cu
Narses


-Pl- - Do 25.01.07 02:08


Delphi-Quelltext
1:
2:
3:
  TDummyClass = class
    procedure DrawTimerTimer(Sender: TObject);
  end;



Delphi-Quelltext
1:
DrawTimer.OnTimer := DrawTimerTimer;                    



Delphi-Quelltext
1:
2:
procedure DummyClass.DrawTimerTimer(Sender: TObject);
begin


Ich behaupte einfach mal es liegt an der fortgeschrittenen Zeit und nicht an mir das es nicht klappt *hust*


Narses - Do 25.01.07 02:13

Moin!

Geht´s jetzt oder nicht? ;)

Abgesehen davon hätte ich eine class procedure genommen, dann brauchst du die Klasse nicht zu instanziieren. ;)

cu
Narses


-Pl- - Do 25.01.07 02:15

Zitat:
Ich behaupte einfach mal es liegt an der fortgeschrittenen Zeit und nicht an mir das es nicht klappt *hust*


Was auch immer eine class procedure ist .. ;-)

Soweit bin ich bei meinen Tutorials noch nicht :P


jaenicke - Do 25.01.07 02:17

user profile iconNarses hat folgendes geschrieben:
Geht´s jetzt oder nicht? ;)

Nein, so kannst ja nicht gehen ;-)

user profile icon-Pl- hat folgendes geschrieben:

Delphi-Quelltext
1:
DrawTimer.OnTimer := DrawTimerTimer;                    

Woher soll Delphi denn wissen wo DrawTimerTimer her kommt? ;-)
Du musst schon die Klasse dazuschreiben...


jaenicke - Do 25.01.07 02:21

user profile icon-Pl- hat folgendes geschrieben:
Was auch immer eine class procedure ist .. ;-)

Also:
Wenn du Prozeduren in einer Klasse verwenden willst, dann benutzt du ja Create um eine Instanz davon im Speicher zu erzeugen.
Schreibst du jetzt statt nur procedure xy; das: class procedure xy;, dann kannst du einfach TDeineKlasse.xy aufrufen ohne Create oder so zu nehmen.

Eine solche Methode ist also auf den Klassentyp bezogen und nicht auf eine bestimmte Instanz der Klasse. Damit kannst du natürlich auch keine Variablen oder so innerhalb der Klasse in eíner solchen Methode nutzen, denn schließlich gibt es die ja nur, wenn du eine Instanz erzeugt hast.


-Pl- - Do 25.01.07 02:25

Ok, vielen Dank, klappt jetzt mit class procedure als auch ohne :D

Merci Merci !