Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Timer in einer Unit (https://www.delphipraxis.net/184358-timer-einer-unit.html)

Popov 19. Mär 2015 17:00

Timer in einer Unit
 
Ich brauche einen Timer in einer Unit oder Klasse (ist noch nicht klar). Bei einem Formular packe ich einfach die Timer Komponente drauf und gut ist es. Nur wie mache ich das wenn ich kein Formular habe?

Ich hab mir die Timer Komponente angeguckt, auf das nötigste, zumindest was ich für nötig halte, gestaucht, und den Code erstellt. Funktionieren tut es, gleich beim ersten Mal. Nur bei mir hat noch nie etwas beim ersten Mal funktioniert, was mich skeptisch macht.

Ich brauch es nicht kompliziert, nur eben, dass etwas im Takt ausgeführt wird. In dem Code der TTimer Komponente wird noch auf WM_TIMER geprüft. Ist das nötig?

Was mich wundert ist auch IDEvent. In der Api-Hilfe steht, dass der Wert nur von Null verschieden sein soll. Bei der Timer-Komponente steht da einfach ein 1. Aber so wie ich es verstanden haben wird der Wert bei KillTimer benötigt um das Ganze zu stoppen. Wie wird hier also zwischen den einzelnen Timern unterschieden?

Delphi-Quellcode:
const
  IDEvent: Integer = 1; //Von Null verschieden

var
  a: Integer = 0;

procedure OnTimer;
begin
  Inc(a)
end;

procedure TimerStop;
begin
  KillTimer(Application.Handle, IDEvent);
end;

procedure TimerStart;
var
  Interval: Cardinal;
begin
  TimerStop;
  Interval := 1000;
  SetTimer(Application.Handle, IDEvent, Interval, @OnTimer);
end;

BadenPower 19. Mär 2015 17:41

AW: Timer in einer Unit
 
Zitat:

Zitat von Popov (Beitrag 1294111)
Nur wie mache ich das wenn ich kein Formular habe?

Selbst erstellen:

Delphi-Quellcode:
MyTimer := TTimer.Create(Self);

himitsu 19. Mär 2015 17:59

AW: Timer in einer Unit
 
Jeder TTimer erstellt sich intern sowieso sein eigenes Form, da es unmöglich ist, abzufragen, ob auf einer Form schon Timer sind und welche IDs Diese belegen, also Nicht-TTimer, so wie Deiner, direkt über die WinAPI.

Zacherl 19. Mär 2015 18:20

AW: Timer in einer Unit
 
Ja die WM_TIMER ist wichtig. Damit deine TTimer Komponente auch funktioniert, benötigst du im selben Thread eine Message Queue (MSDN-Library durchsuchenGetMessage, MSDN-Library durchsuchenTranslateMessage und MSDN-Library durchsuchenDispatchMessage).

Da ich die Window Messages nicht sonderlich mag, implementiere ich mir Timer in Units ohne Formular meistens als Thread, der X Sekunden einfach Sleept.

HolgerX 19. Mär 2015 18:52

AW: Timer in einer Unit
 
Zitat:

Zitat von Zacherl (Beitrag 1294127)
Ja die WM_TIMER ist wichtig. Damit deine TTimer Komponente auch funktioniert, benötigst du im selben Thread eine Message Queue (MSDN-Library durchsuchenGetMessage, MSDN-Library durchsuchenTranslateMessage und MSDN-Library durchsuchenDispatchMessage).

Da ich die Window Messages nicht sonderlich mag, implementiere ich mir Timer in Units ohne Formular meistens als Thread, der X Sekunden einfach Sleept.

Hmm... falsch.. ^^

https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

Da er den Timer mit

SetTimer(Application.Handle, IDEvent, Interval, @OnTimer);

erstellt und somit eine Funktion (@OnTimer) zum Aufrufen mit übergibt, bekommt er gar kein WM_TIMER.

Das WM_TIMER-Event wird nur an das Windows-Handle (hier Application.Handle) geschickt, wenn KEINE Funktion angegeben wird, sondern NULL/NIL.
Die Implementation von WM_TIMER im TTimer kommt daher, das hier wahrscheinlich ein NIL als Funktion angegeben wird und somit an das TTimer ein WM_TIMER geschickt wird.

Die TTimer Komponente erzeugt ein eigenes Windows-Handle und somit ist IDEvent egal, da jeder TTimer eh sein eigenes Handle hat und IDEvent dann im Kontext des Handle nur eindeutig sein muss.

Wird hingegen kein Handle übergeben, so muß IDEvent eindeutig sein, um eine Trennung zwischen den verschiedenen Timer zu erreichen.

Wenn Du wie hier mit Application.Handle arbeitest, brauchst Du für jeden weiteren Timer eine neue IDEvent um einen weiteren Timer mit dem selben Application.Handle zu erstellen.

Zacherl 19. Mär 2015 19:26

AW: Timer in einer Unit
 
Ich bezog mich aber doch ausdrücklich auf die TTimer Komponente, welche wohl die Windows Messages verwendet. Die MSDN-Library durchsuchenSetTimer API habe ich mir zugegebenermaßen aber nicht wirklich angeschaut. Ist mit der Callback Funktion wohl ne brauchbare Alternative zu meiner Thread Lösung :)

HolgerX 19. Mär 2015 19:32

AW: Timer in einer Unit
 
Sorry, dachte du meintest mit ' deine TTimer' den im ersten Posting gezeigten Quellcode.. :(

Zacherl 19. Mär 2015 19:35

AW: Timer in einer Unit
 
Zitat:

Zitat von HolgerX (Beitrag 1294133)
Sorry, dachte du meintest mit ' deine TTimer' den im ersten Posting gezeigten Quellcode.. :(

Achso nene, da habe ich mich wohl auch etwas schlecht ausgedrückt. Danke auf jeden Fall für den Hinweis mit dem Callback :)

BadenPower 19. Mär 2015 20:15

AW: Timer in einer Unit
 
Zitat:

Zitat von HolgerX (Beitrag 1294129)
Wird hingegen kein Handle übergeben, so muß IDEvent eindeutig sein, um eine Trennung zwischen den verschiedenen Timer zu erreichen.

Meiner Meinung nach wird IDEvent komplett ignoriert, wenn Du kein Handle im 1. Parameter übergibst.

Sir Rufo 19. Mär 2015 20:24

AW: Timer in einer Unit
 
Zitat:

Zitat von BadenPower (Beitrag 1294140)
Zitat:

Zitat von HolgerX (Beitrag 1294129)
Wird hingegen kein Handle übergeben, so muß IDEvent eindeutig sein, um eine Trennung zwischen den verschiedenen Timer zu erreichen.

Meiner Meinung nach wird IDEvent komplett ignoriert, wenn Du kein Handle im 1. Parameter übergibst.

Die Doku ist da eindeutig:

Kein hWnd und nIDEvent passt zu keinem existierenden Timer, dann gibt es eine neue Timer ID.

Also wird nicht generell ignoriert.

BadenPower 19. Mär 2015 20:35

AW: Timer in einer Unit
 
Zitat:

Zitat von Sir Rufo (Beitrag 1294143)
Kein hWnd und nIDEvent passt zu keinem existierenden Timer, dann gibt es eine neue Timer ID.

Also wird nicht generell ignoriert.

Also meine Hilfe sagt, dass IDEvent ignoriert wird, wenn das Handle Null ist.

Zitat:

nIDEvent
[in] Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored.
Aber dann kommt die ID für KillTimer nicht durch IDEvent. sondern durch den Rückgabewert der Funktion SetTimer().

Sir Rufo 19. Mär 2015 21:59

AW: Timer in einer Unit
 
Zitat:

Zitat von BadenPower (Beitrag 1294144)
Zitat:

Zitat von Sir Rufo (Beitrag 1294143)
Kein hWnd und nIDEvent passt zu keinem existierenden Timer, dann gibt es eine neue Timer ID.

Also wird nicht generell ignoriert.

Also meine Hilfe sagt, dass IDEvent ignoriert wird, wenn das Handle Null ist.

Zitat:

nIDEvent
[in] Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored.
Aber dann kommt die ID für KillTimer nicht durch IDEvent. sondern durch den Rückgabewert der Funktion SetTimer().

Ich weiß ja nicht wo du schaust, aber ich schaue mir
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
an.
Zitat:

If the hWnd parameter is NULL, and the nIDEvent does not match an existing timer then it is ignored and a new timer ID is generated.
Und ja, wenn dort steht, dass es sich um einen IN Parameter handelt, dann erwarte ich nicht, dass darüber etwas zurückkommt, denn dann wird das als OUT Parameter bezeichnet.

Und zudem steht auch da, was der Rückgabewert bedeutet: Die Timer ID

HolgerX 20. Mär 2015 04:26

AW: Timer in einer Unit
 
Also, Beispiel:

Wenn Du 3 unterschiedliche Timer benötigst, dann brauchst du

a)
3 verschiedene Handles, dann können die IDs gleich sein aber auf jeden Fall > 0.

oder

b)
bei gleichem oder keinem Handle, z.B. dem Application.Handle, 3 verschiedene IDs

Windows MUSS den Timer eindeutig identifizieren können und nutzt hier eine Kombination aus dem Handle UND der ID.

Wenn Du bereits einen Timer mit der gleichen Kombination von Handle und ID erzeugt hast und das SetTimer nochmals mit den gleichen Werten aufrufst, dann wird KEIN neuer Timer angelegt, sondern bei dem bestehendem Timer NUR der Interval und ggf. die Funktion ausgetauscht.

Nur wenn Du eine NEUE Kombination von Handle und ID verwendest, wird ein neuer Timer erzeugt.

So, hoffe nun die Abhängigkeit zwischen Handle und ID verdeutlicht zu haben.. :wink:

BadenPower 20. Mär 2015 08:31

AW: Timer in einer Unit
 
Zitat:

Zitat von Sir Rufo (Beitrag 1294150)
Ich weiß ja nicht wo du schaust, aber ich schaue mir
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
an.

Nachdem ich durch Deinen Post #10 nicht mehr ganz sicher wahr, ob mein Erinnerungsvermögen nicht doch im Stich gelassen hatte, habe ich das getan, ws wir immer und immer wieder predigen und die Delphi-Wunderwaffe gezückt, in dem ich die F1-Taste betätigt habe.

Das Ergebnis war das, welches ich gepostet habe.
Dies entspricht allerdings inhaltlich nicht exakt dem, welches ich aus Deinem Link zu MSDN entnehmen kann.

Vielleicht sollte man die F1-Taste doch deaktivieren und nicht mehr erwähnen.

Zitat:

Zitat von Sir Rufo (Beitrag 1294150)
Und zudem steht auch da, was der Rückgabewert bedeutet: Die Timer ID

Das war ja auch nur eine vorsorgliche Antwort darauf wo ich die TimerID herbeziehe, wenn der, wie ich annahm, Parameter nIDEvent, den man selbst angibt und welchen man normal mit KillTimer() benutzt, ignoriert werden würde.

Popov 20. Mär 2015 15:33

AW: Timer in einer Unit
 
Was kann man abschließend zu dem ersten Code sagen? Ist der Ok, bzw. sauber, oder fehlt da noch was? Wie gesagt, im TTimer Klasse wird da noch nach WM_TIMER geprüft, nur erkenne ich die Notwenigkeit nicht. Kann aber an mir liegen.


Unabhängig dessen, weil ich dann doch unsicher war, habe ich nach weitere Methoden getestet. Dieses Mal habe ich den Tipp befolgt doch den TTimer selbst zu nehmen. Nur wie gesagt, es soll ohne Formular funktionieren, bzw. in einer Unit.

Ich hab zwei Beispiele mit TTimer. Der eigentliche Aufwand dreht sich eigentlich nur um OnTimer.

Delphi-Quellcode:
type
  TMyTimer = class(TTimer)
  public
    procedure TimerTick(Sender: TObject);
  end;

var
  MyTimer: TMyTimer;
  a: Integer = 0;

procedure TMyTimer.TimerTick(Sender: TObject);
begin
  Inc(a);
end;

procedure MyTimerCreate;
begin
  MyTimer := TMyTimer.Create(nil);
  with MyTimer do
  begin
    Interval := 1000;
    Enabled := True;
    OnTimer := TimerTick;
  end;
end;

procedure MyTimerFree;
begin
  MyTimer.Free;
end;

initialization
  MyTimerCreate;

finalization
  MyTimerFree;

end.
Andere Variante. Die Idee fand ich im Internet. Ich weiß nicht ob die besser ist als die erste, sie ist zunindest etwas anders:

Delphi-Quellcode:
type
  TEventHandlers = class
    procedure TimerTick(Sender : TObject);
  end;

var
  MyTimer: TTimer;
  EventHandlers : TEventHandlers;
  a: Integer = 0;

procedure TEventHandlers.TimerTick(Sender: TObject);
begin
  Inc(a);
end;

procedure MyTimerCreate;
begin
  EventHandlers := TEventHandlers.Create();

  MyTimer := TTimer.Create(nil);
  with MyTimer do
  begin
    Interval := 1000;
    Enabled := True;
    OnTimer := EventHandlers.TimerTick;
  end;
end;

procedure MyTimerFree;
begin
  EventHandlers.Free;
  MyTimer.Free;
end;

initialization
  MyTimerCreate;

finalization
  MyTimerFree;

end.
Das sind jetzt also drei Varianten. Welche ist die Beste für Timer in einer Unit ohne Formular?

stahli 20. Mär 2015 15:52

AW: Timer in einer Unit
 
Zitat:

Zitat von Popov (Beitrag 1294247)
Ich hab zwei Beispiele mit TTimer. Der eigentliche Aufwand dreht sich eigentlich nur um OnTimer.

Delphi-Quellcode:
type
  TMyTimer = class(TTimer)
  public
    procedure TimerTick(Sender: TObject);
  end;
...

In dem Sinne wollte ich Dir gestern eigentlich antworten, hatte das dann aber verworfen weil ich meinte, Du suchst eine andere Lösung (ohne TTimer).

Popov 20. Mär 2015 16:04

AW: Timer in einer Unit
 
Zitat:

Zitat von stahli (Beitrag 1294250)
In dem Sinne wollte ich Dir gestern eigentlich antworten, hatte das dann aber verworfen weil ich meinte, Du suchst eine andere Lösung (ohne TTimer).

Eigentlich suche ich auch eine Lösung ohne TTimer. Der Grund ist aber weniger eine Abneigung gegen den TTimer, als die Frage ob Komponenten, selbst wenn sie nicht sichtbar sind, in einer reinen Unit etwas zu suchen haben?

EWeiss 20. Mär 2015 16:20

AW: Timer in einer Unit
 
Zitat:

Zitat von Popov (Beitrag 1294252)
Zitat:

Zitat von stahli (Beitrag 1294250)
In dem Sinne wollte ich Dir gestern eigentlich antworten, hatte das dann aber verworfen weil ich meinte, Du suchst eine andere Lösung (ohne TTimer).

Eigentlich suche ich auch eine Lösung ohne TTimer. Der Grund ist aber weniger eine Abneigung gegen den TTimer, als die Frage ob Komponenten, selbst wenn sie nicht sichtbar sind, in einer reinen Unit etwas zu suchen haben?

Warum vermischst du dann TTimer mit TMMTime?
Die API Lösung basiert auf MMSystem (TMMTime)

gruss

BadenPower 20. Mär 2015 16:30

AW: Timer in einer Unit
 
Zitat:

Zitat von Popov (Beitrag 1294252)
Der Grund ist aber weniger eine Abneigung gegen den TTimer, als die Frage ob Komponenten, selbst wenn sie nicht sichtbar sind, in einer reinen Unit etwas zu suchen haben?

Eine Komponente ist doch auch nur eine stink normale Klasse, wie z.B. TStringList, welcher die zusätzliche Möglichkeit gegeben wurde auf der Form platziert zu werden, damit sie automatisch erstellt wird und man Werte im OI beabeiten kann.

Popov 20. Mär 2015 16:34

AW: Timer in einer Unit
 
@BadenPower

Ist schon klar. Man kann aber auch die Verandatür öffnen und sein Auto im Wohnzimmer parken. Gehen tut es, womit die Parkplatzprobleme vorbei wären, man fragt sich aber trotzdem stets ob es die feine saubere Art ist.

himitsu 20. Mär 2015 16:51

AW: Timer in einer Unit
 
Eigentlich würde ich lieber ein OOP-Turorial empfehlen, aber hier mal in Kurz, mit Kommentaren.
Delphi-Quellcode:
type
  TMyTimer = class(TTimer)
  protected
    procedure DoOnTimer; override;
  public
    constructor Create(Owner: TComponent); override;
    //procedure TimerTick(Sender: TObject); // wenn man schon vererbung benutzt, dann doch bitte richtig -> DoOnTimer
  end;

var
  MyTimer: TMyTimer; // OK, da mach ich noch mit, aber natürlich nur in Implementation deklariert, aber eigentlich als private Class-Var in die Klasse
  //a: Integer = 0; // warum ist das global, wo es doch nur im Timer benutzt wird?

//procedure TMyTimer.TimerTick(Sender: TObject);
procedure TMyTimer.DoOnTimer;
begin
  Tag := Tag + 1; //Inc(FCount); // privates Feld "FCount: Integer" mit Property oder das Entwicklerproperty "Tag"
  inherited;
end;

constructor TMyTimerCreate(Owner: TComponent);
begin
  inherited;
  Interval := 1000;
end;

//procedure MyTimerCreate;
//begin
//  MyTimer := TMyTimer.Create(nil); // alleine in Prozedur, also sinnlos hier
//  with MyTimer do
//  begin
//    Interval := 1000; // nja, 1000 ist zwar auch default, aber wenn es sein muß, dann wenigstens in den Constructor
//    Enabled := True; // es ist per Default immer Enabled
//    OnTimer := TimerTick; // sinnlos
//  end;
//end;

//procedure MyTimerFree;
//begin
//  MyTimer.Free;
//end;

initialization
  //MyTimerCreate;
  MyTimer := TMyTimer.Create(nil);

finalization
  MyTimer.Free; //MyTimerFree;

end.

Popov 20. Mär 2015 17:06

AW: Timer in einer Unit
 
@himitsu

Danke für die Kommentare, nur...

das war kein Auszug aus der fertigen Unit, es war nur ein Test. Mehr nicht. Nur ein Test.

Es ist toll, dass du eine Klasse konstruiert hast, nur wozu? Welchen Sinn hat das was du gemacht hast? Was soll ich damit? Was soll ich damit anfangen? Wenn ich eine Klasse brauche, dann nehme ich gleich die TTime Komponente. Letztendlich hast du einen Apfel genommen, ein Herzchen draufgeklebt, und das Ergebnis ist ein Apfel.

Bevor du also unnötige Verbesserungsvorschläge machst, frag lieber ob das die Frage ist.

himitsu 20. Mär 2015 17:14

AW: Timer in einer Unit
 
Die Klasse hattest du auch schon, nur so, wie der Code war, hätte man TTimer nicht ableiten müssen, da praktisch alle Funktion außerhalb lag. :zwinker:

Dejan Vu 20. Mär 2015 17:39

AW: Timer in einer Unit
 
Du hast also eine Unit und keine Klasse, aber eine Prozedur?

Ich würde keinen Timer ableiten, sondern das über den TEventHandler machen.

Aber eigentlich würde ich eine Klasse schreiben und einer der Methoden der Klassen dem 'OnTimer' zuweisen.

Aber wenn irgendwo legacy code rummschwirrt, würde ich mir die Mühe auch nicht machen und das kleinste Übel nehmen: Den TEventhandler.

Ich hab übrigens auch lange gedacht, so eine Komponente ist ein ziemlich großer Klumpen, denn ich bloß nicht in schlanken Klassen/Units verwenden darf. Aber -pah- drauf gebongt. Erstens sind die nicht groß und zweitens ist das Delphi und wenn Komponenten rumliegen, kann man sie doch benutzen. Ich würde jetzt natürlich auch kein TStringGrid nehmen, um ein Array of Array of String abzulegen, aber so ein Timer ist schon schlank.

Aber wenn Du drauf Wert legst: Wieso nicht einen Threaded-Timer? Also schlanker gehts nimmer.

jaenicke 20. Mär 2015 18:14

AW: Timer in einer Unit
 
Nur weil man kein Formular hat, heißt das ja nicht, dass man keine Komponenten als solche nutzen kann. Im Grunde ist der Fall hier ein Paradebeispiel für ein Datenmodul. Da kommt der Timer drauf, wird ganz normal genutzt, und der Rest der Funktionalität kommt auch in die Datenmodul-Klasse.

Popov 20. Mär 2015 18:20

AW: Timer in einer Unit
 
@himitsu

Ich will dich nicht dafür kritisieren, weil du etwas richtig machen willst, aber das ist ein Programmiererforum. Warum muss der Code optimiert sein? Kann doch jeder selbst machen. Wenn einer nicht weiß wie er A und B in einer Klasse addieren kann, dann schreibe ich in einer Button1Click Prozedur wie man A und B addiert, denn das ist wohl das Problem. Ich packe das nicht in eine Klasse, denn ich gehe davon aus, dass der Fragesteller weiß wie man eine Klasse schreibt. Ich konzentriere mich auf das Problem.

Die Beispiele oben beschreiben mögliche Lösungen des Problems, in Einzelteile zerlegt. Der eine Block beschreibt das eine Teil, der andere ein anderes. Wer wissen will wie man Klassen programmieren kann, der kann fragen wie man Klassen programmieren kann. Wer wissen will wie man das Beispiel eleganter programmieren kann, den kann danach fragen.


@Dejan Vu

Das was ich vorhabe ist etwas komplexer. Mich interessiert es nicht wirklich wie man mit Inc a erhöhen kann. Vielmehr ist es so, dass ich beim Aufruf einer Prozedur eine weitere für eine bestimmte Zeit getaktet starten will. Womit letztendlich mein erstes Beispiel im Post #1 der optimale wäre, denn da muss ich keine Objekte erzeugen oder freigeben, sondern nur den Timer starten und stoppen. Ist für eine Unit optimaler. Trotzdem habe ich auch andere Möglichkeiten geprüft (und die Ergebnisse gepostet falls einer eine ähnliche Frage hat).


@jaenicke

Ok, danke. Das mit der Komponente und Formular war etwas was ich zwar immer gemacht habe, aber stets nach anderen Möglichkeiten gesucht habe.

himitsu 20. Mär 2015 23:35

AW: Timer in einer Unit
 
Vielleicht nicht optimiert, aber wenigstens "aufgeräumt"? :angle2:

Popov 21. Mär 2015 00:38

AW: Timer in einer Unit
 
Du erinnerst mich etwas an ein HTML-Forum für Anfänger, in dem ich früher (so vor 10 Jahren) gelegentlich war. Regelmäßig wie das Amen in der Kirche kam dort ein Newbie vorbei der sich an einer Webseite versuchte und etwas in zwei Spalten schreiben wollte. Die simple Lösung die damals üblich war und selbst von wichtigen Portale noch genutzt wurde war die Tabelle. Man nehme einen Tabellen-Tag, einen Zeilen-Tag und zwei Spalten-Tags. Fertig.

Dafür muss man nichts lernen. Das sagt man dem Newbie, zeigt es ihm und er ist glücklich. Der will ja nichts groß lernen, er will eine Webseite mit Infos erstellen. Aber wehe einer kam mit der Tabellenlösung an.

Denn da gab es die Experten, und für die war die Tabellenlösung keine Lösung. Um etwas in zwei Spalten zu schreiben muß man erst CSS lernen - das war deren Antwort auf die Frage. Ohne CSS geht es nicht.

Da gab es dauerhaft Diskussionen. Ich weiß nicht ob je einer der Newbie seine Webseite vollendet hat oder gar extra wegen der zwei Spalten CSS gelernt hat. Aber das war in dem Forum nie wirklich wichtig. Wichtig war, dass man für Spalten CSS drauf haben sollte.

Dejan Vu 21. Mär 2015 06:27

AW: Timer in einer Unit
 
Und wer ist hier bei deinem Vergleich hier der Newbie?

Ein Programmierforum ist sehr wohl und zuallererst dazu da, Code nicht nur zu zeigen, sondern auch zu optimieren. Natürlich soll man die TE nicht überfordern, und insofern wäre ein echter Newbie bestimmt überfordert. Nun zähle ich dich aber nicht so direkt zu den, die froh sind, überhaupt die Compile-Funktion entdeckt zu haben.

Wenn Du in 2015 in einem Bauforum das Bohren eines Lochen in einer Wand damit demonstrierst, indem Du eine Lehmwand hochziehst, darf man schon darauf hinweisen, das es auch andere, bessererere Baustoffe gibt. Vor allen Dingen, weil bei einer dermaßen fundamentalen Frage auch Interessierte vorbeischauen, die neben den einfachen Tipps auch Optimierungen zu sehen bekommen.

Sir Rufo 21. Mär 2015 09:26

AW: Timer in einer Unit
 
Hier mal ein Minimalst-Beispiel, was auch komplett auf ein Handle verzichtet
Delphi-Quellcode:
unit Unit1;

interface

uses
  {Winapi.}Windows;

// Startet den Timer oder
// setzt ein neues Intervall für einen aktiven Timer
procedure TimerStart( Interval: UINT );
// Stoppt den Timer
procedure TimerStop;

implementation

var
  nIDEvent: UINT_PTR = 0; // Beim Start kein Timer, also nIDEvent = 0

procedure OnTimer;
begin
  // hier irgendwas machen
end;

procedure TimerStop;
begin
  if KillTimer( 0, nIDEvent )
  then
    nIDEvent := 0; // Wenn der Timer entfernt werden konnte, dann nIDEvent wieder auf 0 setzen
end;

procedure TimerStart( Interval: UINT );
begin
  nIDEvent := SetTimer( 0, nIDEvent, Interval, @OnTimer );
end;

end.

Popov 21. Mär 2015 10:56

AW: Timer in einer Unit
 
@Dejan Vu

Vielleicht hast du auch Recht, denn irgendwann wird es dann doch peinlich wenn man merkt, dass jemand denkt, dass man das hier
Delphi-Quellcode:
procedure MyTimerCreate;
begin
  MyTimer := TMyTimer.Create(nil);
  with MyTimer do
  begin
    Interval := 1000;
    Enabled := True;
    OnTimer := TimerTick;
  end;
end;

initialization
  MyTimerCreate;
nur deshalb so geschrieben hat, weil man es nicht besser drauf hat, und nicht, weil dahinter eine Absicht steckt und man an die denkt, die evtl. in den nächsten Jahren danach suchen und eher den Sinn verstehen wollen.

Und für die, die noch immer nicht verstanden haben wieso der Code so zerlegt ist und es eine procedure TimerTick gibt, den Grund erkennen die, die das Problem man haben werden. Denn es ist nicht ohne Grund so. Denn gelegentlich braucht man die Prozedur nicht. Also ist sie separat. Ich werde das jetzt aber nicht vertiefen.

HolgerX 21. Mär 2015 13:39

AW: Timer in einer Unit
 
Hi.hi..
:wink:

Nur ne kleine Anmerkung:

SetTimer( 0, nIDEvent, Interval, @OnTimer );

benötigt eine nIDEvent > 0 !!

Also hier einfach

SetTimer( 0, 1, Interval, @OnTimer );

Da mit dieser Minimalroutine eh nur ein Teimer erzeugt werden kann :)

Zitat:

Zitat von Sir Rufo (Beitrag 1294316)
Hier mal ein Minimalst-Beispiel, was auch komplett auf ein Handle verzichtet
Delphi-Quellcode:
unit Unit1;

interface

uses
  {Winapi.}Windows;

// Startet den Timer oder
// setzt ein neues Intervall für einen aktiven Timer
procedure TimerStart( Interval: UINT );
// Stoppt den Timer
procedure TimerStop;

implementation

var
  nIDEvent: UINT_PTR = 0; // Beim Start kein Timer, also nIDEvent = 0

procedure OnTimer;
begin
  // hier irgendwas machen
end;

procedure TimerStop;
begin
  if KillTimer( 0, nIDEvent )
  then
    nIDEvent := 0; // Wenn der Timer entfernt werden konnte, dann nIDEvent wieder auf 0 setzen
end;

procedure TimerStart( Interval: UINT );
begin
  nIDEvent := SetTimer( 0, nIDEvent, Interval, @OnTimer );
end;

end.


Sir Rufo 21. Mär 2015 16:20

AW: Timer in einer Unit
 
Zitat:

Zitat von HolgerX (Beitrag 1294337)
Hi.hi..
:wink:

Nur ne kleine Anmerkung:

SetTimer( 0, nIDEvent, Interval, @OnTimer );

benötigt eine nIDEvent > 0 !!

Könntest du das einmal erläutern, warum. Dann können wir das bei MS einreichen, auf dass die ihre Doku anpassen, denn die wäre dann ja wohl falsch.

Evtl. liegt es auch daran, dass ich es mir angewöhnt habe den gesamten Abschnitt der Dokumentation zu lesen und nicht nur das erste Schlagwort.

HolgerX 22. Mär 2015 03:28

AW: Timer in einer Unit
 
Schau doch mal in den Post Nr. 5 von diesem Thema, da habe ich versucht es zu erklären...:wink:

https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

Zitat:

nIDEvent [in]
Type: UINT_PTR
A nonzero timer identifier. If the hWnd parameter is NULL, and the nIDEvent does not match an existing timer then it is ignored and a new timer ID is generated. If the hWnd parameter is not NULL and the window specified by hWnd already has a timer with the value nIDEvent, then the existing timer is replaced by the new timer. When SetTimer replaces a timer, the timer is reset. Therefore, a message will be sent after the current time-out value elapses, but the previously set time-out value is ignored. If the call is not intended to replace an existing timer, nIDEvent should be 0 if the hWnd is NULL.

OK, da weiß wohl MS selber nicht was es will.

A nonzero timer identifier.
..nIDEvent should be 0 if the hWnd is NULL


Zitat:

Zitat von Sir Rufo (Beitrag 1294343)
Zitat:

Zitat von HolgerX (Beitrag 1294337)
Hi.hi..
:wink:

Nur ne kleine Anmerkung:

SetTimer( 0, nIDEvent, Interval, @OnTimer );

benötigt eine nIDEvent > 0 !!

Könntest du das einmal erläutern, warum. Dann können wir das bei MS einreichen, auf dass die ihre Doku anpassen, denn die wäre dann ja wohl falsch.

Evtl. liegt es auch daran, dass ich es mir angewöhnt habe den gesamten Abschnitt der Dokumentation zu lesen und nicht nur das erste Schlagwort.


jaenicke 22. Mär 2015 06:14

AW: Timer in einer Unit
 
Zitat:

Zitat von HolgerX (Beitrag 1294384)
OK, da weiß wohl MS selber nicht was es will.

A nonzero timer identifier.
..nIDEvent should be 0 if the hWnd is NULL

Es ist vielleicht etwas missverständlich ausgedrückt, aber gemeint ist, dass die ID um einen Timer zu identifizieren nicht 0 sein kann, sondern bei 1 startet. Ansonsten hätte jemand auf die Idee kommen können bei 0 anzufangen mit dem ersten Timer.
Sprich es heißt nicht, dass der Parameter nicht 0 sein darf, sondern der Identifizierer für einen Timer.

In dem Fall muss man das einfach nur wörtlich nehmen...

Dejan Vu 22. Mär 2015 07:32

AW: Timer in einer Unit
 
:thumb: aber der Event wird nur 1x ausgelöst, d.h. es handelt sich nicht um einen periodischen Timer (den man aber sehr leicht anhand des Codes erstellen kann)

Sir Rufo 22. Mär 2015 07:35

AW: Timer in einer Unit
 
Zitat:

Zitat von Dejan Vu (Beitrag 1294388)
:thumb: aber der Event wird nur 1x ausgelöst, d.h. es handelt sich nicht um einen periodischen Timer (den man aber sehr leicht anhand des Codes erstellen kann)

Wo wie was wann wird da nur einmal etwas ausgelöst? Der Timer, wenn erfolgreich gesetzt, löst nach jedem Intervall aus bis es den Timer nicht mehr gibt.

BadenPower 22. Mär 2015 11:24

AW: Timer in einer Unit
 
Zitat:

Zitat von Dejan Vu (Beitrag 1294388)
:thumb: aber der Event wird nur 1x ausgelöst, d.h. es handelt sich nicht um einen periodischen Timer (den man aber sehr leicht anhand des Codes erstellen kann)

Einmal abgesehen davon, dass die Aussage falsch ist, hätte man dennoch als Antwort die Code-Änderung posten können, welche dann die angebliche richtige Lösung enthalten würde.

So ist es halt nur wieder das übliche BlaBla.

Dejan Vu 22. Mär 2015 12:22

AW: Timer in einer Unit
 
Ich hatte die MSDN-Beschreibung so verstanden, aber -so im nachhinein- wäre das auch ziemlich blöd, wenn es nur 1x gefeuert würde.
Zitat:

Zitat von BadenPower (Beitrag 1294396)
So ist es halt nur wieder das übliche BlaBla.

Niveau ist das Denkmal des Verstandes. ;-)

Popov 22. Mär 2015 12:45

AW: Timer in einer Unit
 
Ich hab das mal übersetzt:

SetTimer
Code:
function SetTimer(Wnd: HWnd; IDEvent: Integer; Elapse: Word; TimerFunc: TFarProc): Word;
Die Funktion SetTimer erzeugt ein System-Timer-Ereignis. Ein Time-Out-Wert wird festgelegt. Immer wenn ein Time-Out eintritt, sendet das System eine WM_TIMER-Meldung an die installierte Anwendungswarteschlange, oder übergibt die Meldung an eine anwendungsdefinierte TimerProc-Callback-Funktion.

ParameterBeschreibung
WndLegt das Fenster fest, das dem Timer zugeordnet werden soll. Ist der Parameter TimerFunc nil, erhält die mit diesem Fenster verbundene Fenster-Prozedur die Meldungen WM_TIMER von dem Timer. Ist dieser Parameter Null, wird kein Fenster mit dem Timer verbunden.
IDEventLegt einen von Null verschiedenen Bezeichner für ein Timer-Ereignis fest. Ist der Parameter Wnd Null, wird dieser Parameter ignoriert.
ElapseBestimmt die abgelaufene Zeit zwischen Timer-Ereignissen in Millisekunden.
TimerFuncBestimmt die Adresse der Prozedurinstanz der Callback-Funktion, die die Meldungen WM_TIMER weitergibt. Ist dieser Parameter nil, werden die Meldungen WM_TIMER in der Anwendungswarteschlange plaziert, und das hwnd-Mitglied der Struktur TMSG enthält das durch den Parameter Wnd bestimmte Fenster-Handle. Weitere Informationen finden Sie in der Beschreibung der Callback-Funktion TimerProc

Rückgabewert
Der Rückgabewert legt den Integer-Bezeichner für das neue Timer-Ereignis fest, wenn der Parameter Wnd Null ist, und die Funktion erfolgreich ausgeführt wurde. Eine Anwendung übergibt diesen Wert an die Funktion KillTimer, um das Timer-Ereignis zu beseitigen. Der Rückgabewert ist ungleich Null, wenn der Parameter Wnd ein gültiges Fenster-Handle ist, und die Funktion erfolgreich ausgeführt wurde. Andernfalls ist der Rückgabewert Null.

Hinweis
Timer sind eine eingeschränkt verfügbare, globale Ressource. Aus diesem Grund ist es wichtig, daß eine Anwendung den durch die Funktion SetTimer zurückgegeben Wert überprüft, um sicherzustellen, daß ein Timer verfügbar ist.

Um eine Timer-Funktion zu installieren, muß TimerFunc eine Adresse der Prozedurinstanz einer Callback-Funktion bestimmen und die Funktion muß in der Moduldefinitionsdatei der Anwendung exportiert werden. Die Adresse sollte mit Hilfe der Funktion MakeProcInstance erzeugt werden.

Die Callback-Funktion muß die Pascal-Aufrufkonvention verwenden und als FAR deklariert werden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:49 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz