dsTimer

{
A timer component. Start, stop, split and reset are implemented.
}


{
TdsTimer (how much time elapsed)

There are many times, some would like to know, how much time things
took to do something. In this article, we will review how to build
that kind of timer.

Don't mix things up with TTimer, which you can find on Delphi components
palette (System). It is possible though, to measure time with this timer
as well, but results are not very good. Windows API knows function GetTickCount.
You can read all about this function in the API help. For us, it's important,
that this function works very good. You can call it this way:

t := GetTickCount

The result are miliseconds elapsed from Windows startup.
Since we want this component to appear on the components palette and we want
to be able to drop it on the form, our component will descant from TComponent.
All classes that descant from TComponent can appear on the palette.

Start with a skeleton for a new component. Now stop for a moment and think
what functionality would you like to provide.
What do we need?
Start, stop, reset. Maybe split time as well. Let's define our class.
First we need few procedures. Those are Start, Stop, Reset. Then we need
two functions, that will return results. Those two are Time and Split.
Now our class should look like this:
}

type
  TdsTimer1 = class(TComponent)
  private
    FElapsed, FStartTime, FStopTime: Cardinal;
    FRunning: Boolean;
  public
    procedure Start;
    procedure Stop;
    procedure Reset;

    function Split: Cardinal;
    function Time: Cardinal;

    property Running: Boolean read FRunning;
  end;
  
{
Running property will tell us if timer is running. Now let's see the procedures:
}

procedure TdsTimer1.Start;
begin
  if FRunning then
    raise Exception.Create('Timer is already running');

  FRunning := true;

  FStartTime := GetTickCount;
end;

procedure TdsTimer1.Stop;
begin
  FStopTime := GetTickCount;

  if not FRunning then
    raise Exception.Create('Timer is not running');

  FElapsed := FElapsed + (FStopTime - FStartTime);
  FRunning := false;
end;

{
Any questions here?
In Start we first check if timer is already running. If so, raise exception
otherwise set Running to true and get time.
In Stop, first get time. Then check if timer is running. If not, raise
exception. At the end, calculate time ellapsed.
}

procedure TdsTimer1.Reset;
begin
  if FRunning then
    raise Exception.Create('Timer is running');

  FElapsed := 0;
end;

function TdsTimer1.Split: Cardinal;
begin
  if not FRunning then
    raise Exception.Create('Timer is not running');

  Result := GetTickCount - FStartTime + FElapsed;
end;

{
Here are Reset and Split. Things are the same. Check for Running and then
do the apropriate thing.
Now let's write the last procedure that tells us how much time elapsed.
}

function TdsTimer1.Time: Cardinal;
begin
  if FRunning then
    raise Exception.Create('Timer is running');

  Result := FElapsed;
end;

{
And that's about everything. All you have to do is write some code to test our timer.
Declare:
  t: TdsTimer
  
in private section of our form. Put two labels and four buttons on the form and write:
}

procedure TForm1.FormCreate(Sender: TObject);
begin
  t := TdsTimer1.Create(Self);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  t.Start;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  t.Stop;
  Label1.Caption := 'Elapsed:';
  Label2.Caption := IntToStr(t.Time);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  Label1.Caption := 'Split:';
  Label2.Caption := IntToStr(t.Split);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  t.Reset;
end;