2

Possible Duplicate:
Delphi Timer: Time before next event

How to get current timeleft when timer will be executed ?

for example:

I create a timer with interval 60 000

procedure TForm1.my_Timer(Sender: TObject);
begin
  // do something
end;

Then I create another timer (interval 1000) which reason is to get the timeleft of the first timer

procedure TForm1.second_Timer(Sender: TObject);
begin
  second_Timer.Interval := 1000;
  Label1.Caption := IntToStr(my_Timer.timeleft); // How ???
end;

Thanks.

Community
  • 1
  • 1
jmp
  • 2,456
  • 3
  • 30
  • 47

3 Answers3

5

You can't get this information from the timer. The best you can do is make a note of when the timer last fired and work it out for yourself. For example you can use TStopwatch to do this.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 4
    However, with the 'unpredictability' of window timers in real-world applications, this can be wrong. – Warren P Jan 06 '12 at 20:35
  • When was the `Diagnostics` unit added? – Andreas Rejbrand Jan 06 '12 at 20:46
  • 1
    @Andreas It's present in [D2010](http://docwiki.embarcadero.com/VCL/2010/en/Diagnostics). I only found it yesterday so clearly I haven't been paying enough attention. – David Heffernan Jan 06 '12 at 20:50
  • I can confirm it was added in D2010. Nick Hodges wrote about it, but I can't find his blogs from Embarcadero anymore. – LU RD Jan 06 '12 at 22:25
  • @LURD If Andreas is asking about it, it cannot be in D2009 which is the version that he has – David Heffernan Jan 06 '12 at 22:27
  • @WarrenP The `QueryperformanceCounter` is quite precise. I use it in my timers and cannot detect a deviation within the milliseconds range (it should be able to count nanoseconds for what it's worth). If TStopWatch uses this that could be sufficient. I don't know what precision waza123 wants. – Arnold Jan 07 '12 at 14:09
  • The error I am talking about is the non-determinacy of the WM_TIMER message (intentional in Win API design) not the error in QueryPerformanceCounter, which by the way, does have its own problems, but not on current generation of hardware. In the old Pentium 4 era, and prior, QueryPerformanceCounter had some serious problems which have since been fixed. – Warren P Jan 07 '12 at 14:20
0

TTimer itself does not have have this capability. One option would be to use the tag property of the first timer to store the remaining time like so:

procedure TForm1.MyTimerTimer(Sender: TObject);
begin
  MyTimer.Tag := MyTimer.Interval;
  // Do something
end;

procedure TForm1.Second_TimerTimer(Sender: TObject);
begin
  MyTimer.Tag := MyTimer.Tag - Second_Timer.Interval;
  Label1.Caption := 'Time Left '+IntToStr(MyTimer.Tag);
end;
Mike W
  • 1,276
  • 8
  • 10
  • Since timers don't guarantee to fire on time this will likely become inaccurate quite rapidly. You'd be better off keeping track of time yourself, e.g. with `TStopwatch`. – David Heffernan Jan 06 '12 at 20:36
  • Agreed, but that's always going to be a problem using timers like the original poster is trying to do. However, this at least resets itself on every interval of the large timer so it won't drift continuously. – Mike W Jan 06 '12 at 20:40
  • Indeed, but it's not implausible that you may have a second or two of drift and it would get worse with a longer large timer. Since `TStopwatch` is so cheap and easy it makes sense to use it in my view. – David Heffernan Jan 06 '12 at 20:42
  • .Tag will be set only on timers ends. – jmp Jan 06 '12 at 20:46
  • Yes, you'd have to initialize the tag on startup. – Mike W Jan 06 '12 at 20:48
-2

Just created my hack way, I'm using two global vars

var
  my_timer_interval_hack : integer;
  my_timer_timeleft_hack : integer;

procedure TForm1.my_Timer(Sender: TObject);
begin
  // do something


  // hack, reset timer TimeLeft
  my_timer_timeleft_hack := my_Timer.Interval;
end;



procedure TForm1.second_Timer(Sender: TObject);
begin
  second_Timer.Interval := 1000;

  // hack get timeleft from my_timer
  my_timer_timeleft_hack := my_timer_timeleft_hack - 1000;
  if my_timer_timeleft_hack <= 0 then
    my_timer_timeleft_hack := my_timer.Interval;

  Label1.Caption := IntToStr(my_timer_timeleft_hack);
end;
jmp
  • 2,456
  • 3
  • 30
  • 47
  • As far as I can see, you are only using *one* global variable. Anyhow, the code above either shows `Timer1.Interval` or `Timer1.Interval - 1000`... – Andreas Rejbrand Jan 06 '12 at 21:09
  • 1
    Really, use a stopwatch for this it is far far cleaner to do so. Nobody says that you have to use a timer to count the passing of time. – David Heffernan Jan 06 '12 at 21:14
  • Why you even need two timers? Just use one high resolution and trigger //do something every 60th second or so.. – Harriv Jan 06 '12 at 21:22
  • I think `_kludge` suffix is more applicable for these identifiers ;-) – OnTheFly Jan 06 '12 at 21:48