| Till | Lab Report |
Purpose
The purpose of this project is to create a
count-down timer to count down in days, hours, minutes, and seconds to any specified
target date and time.
Materials and Equipment
Software Requirements
Windows 95/98
Delphi 3/4/5 (to recompile)
Till.EXEHardware Requirements
VGA display
Procedure
![]()
If desired, change the target time by pressing the Setup button. Note the Target Date and Target Time are in your local time. The time shown in the example below is for U.S. Eastern Time. For the central time zone, the Target Time should be 11:00:00; for Mountain Time, the Target Time should be 10:00:00; and for the West Coast, the Target Time should be 9:00:00, etc.


When the target time has been reached, the display will show a flashing "0 0:00:00", either in "normal" mode, or on the task bar.

Discussion
Several actions are taken in the FormCreate method for TCountDownForm.
One of these actions is to establish OnMinimize and OnRestore
methods for when the form is minimized:
| Application.OnRestore := AppOnRestore; Application.OnMinimize := AppOnMinimize; DisplayState := wsNormal; |
The TILL.INI file contains several important data times, including the Title, Target Time, Font Size, and the Form's Top and Left position properties.
| // Default if no .INI file is present TopMessage.Caption := 'Till Next Year'; TargetTime := EncodeDate(StrToInt(FormatDateTime('yyyy',Now))+1,1,1); // Read .INI file with defaults Filename := ChangeFileExt(ParamStr(0), '.INI'); IF FileExists(Filename) THEN BEGIN IniFile := TIniFile.Create(Filename); TRY Top := IniFile.ReadInteger(FORMSection, FORMTop, Top); Left := IniFile.ReadInteger(FORMSection, FORMLeft, Left); FontSize := IniFile.ReadInteger(OPTIONSSection, OPTIONSFontSize, Days.Font.Size); UpdateFontSize(FontSize); TopMessage.Caption := IniFile.ReadString(OPTIONSSection,OPTIONSTitle, 'Till Next Year'); DateTimeString := Inifile.ReadString(OPTIONSSection,OPTIONSTargetDateTime,''); IF LENGTH(DateTimeString) > 0 THEN TargetTime := StrToFloat(DateTimeString) FINALLY IniFile.Free END END; |
The FormClose updates the Top and Left properties in the TILL.INI in case the screen was moved.
The main work of the program is performed in the TimerTickTimer method of the TimerTick object:
procedure TCountDownForm.TimerTickTimer(Sender: TObject);
VAR
dd : Cardinal;
Fraction : TDateTime;
hh : WORD;
Milliseconds: WORD;
mm : WORD;
ss : WORD;
TimeDiff : TDateTime;
begin
TimeDiff := TargetTime - Now;
IF TimeDiff < 0
THEN BEGIN
UpdateNumericDisplay (0, 0, 0, 0);
TimerTick.Enabled := FALSE; // Turn off timer messages
TimerDone.Enabled := TRUE; // Separate processing when done
DoneState := 0;
// Use clRed to indicate time has elapsed
Days.Font.Color := clRed;
Hours.Font.Color := Days.Font.Color;
Colon1.Font.Color := Days.Font.Color;
Minutes.Font.Color := Days.Font.Color;
Colon2.Font.Color := Days.Font.Color;
Seconds.Font.Color := Days.Font.Color
END
ELSE BEGIN
dd := Trunc(TargetTime - Now); // Full days remaining
Fraction := Frac(TargetTime - Now); // Fractional days remaining
DecodeTime (Fraction , hh, mm, ss, Milliseconds);
UpdateNumericDisplay (dd, hh, mm, ss);
END
end; |
The UpdateNumericDisplay method updates the main form, or changes the caption shown on the Task Bar icon when the form is minimized. A lot of extra logic is present to dynamically change the main form for different sizes of numeric values.
PROCEDURE TCountDownForm.UpdateNumericDisplay (CONST dddd: Cardinal;
CONST hh, mm, ss: WORD);
VAR
j : INTEGER;
WidthTitle : INTEGER;
WidthNumerics: INTEGER;
BEGIN
IF DisplayState = wsMinimized
THEN BEGIN
Application.Title := Format('%2d %2d:%2.2d:%2.2d', [dddd,hh,mm,ss]);
END
ELSE BEGIN
// Use separate fields to avoid flicker when values don't change
CountDownForm.Days.Caption := Format('%d', [dddd]);
CountDownForm.Hours.Caption := Format('%d', [hh]);
CountDownForm.Minutes.Caption := Format('%2.2d', [mm]);
CountDownForm.Seconds.Caption := Format('%2.2d', [ss]);
// Adjust geometry of labels -- vertical first
// Top position of Days/Hours/Minutes/Seconds labels
// Size of TopMessage is fixed. Top of numeric labels is fixed.
j := TopMessage.Height + Days.Height;
DaysLabel.Top := j;
HoursLabel.Top := j;
MinutesLabel.Top := j;
SecondsLabel.Top := j;
CountDownForm.ClientHeight := j + DaysLabel.Height;
// Adjust geometry of labels -- horizontally
WidthTitle := SpeedButtonSetup.Width +
TopMessage.Width +
SpeedButtonSetup.Width;
WidthNumerics := Colon1.Width DIV 2 +
Days.Width +
Colon1.Width +
Hours.Width +
Colon1.Width +
Minutes.Width +
Colon2.Width +
Seconds.Width +
Colon1.Width DIV 2;
IF WidthTitle > WidthNumerics
THEN ClientWidth := WidthTitle
ELSE ClientWidth := WidthNumerics;
TopMessage.Left := (ClientWidth - TopMessage.Width) DIV 2;
Days.Left := Colon1.Width DIV 2;
Hours.Left := Days.Left + Days.Width + Colon1.Width;
Colon1.Left := Hours.left + Hours.Width;
Minutes.Left := Colon1.Left + Colon1.Width;
Colon2.Left := Minutes.Left + Minutes.Width;
Seconds.Left := Colon2.Left + Colon2.Width;
DaysLabel.Left := Days.Left + (Days.Width - DaysLabel.Width) DIV 2;
HoursLabel.Left := Hours.Left + (Hours.Width - HoursLabel.Width) DIV 2;
MinutesLabel.Left := Minutes.Left + (Minutes.Width - MinutesLabel.Width) DIV 2;
SecondsLabel.Left := Seconds.Left + (Seconds.Width - SecondsLabel.Width) DIV 2
END
END {UpdateDisplay};
|
Before using the approach shown above, I considered using a Form.OnResize and adjusting the font so the text would fit. I concluded setting the font and adjusting the size of all the TLabels was an easier approach.
The FormCreate of the FormSetup definition included special DateTime_SetFormat calls to establish a 4-digit year and a 24-hour clock with the two TDateTimePickers used on this form:
USES CommCtrl; // DateTime_SetFormat procedure TFormSetup.FormCreate(Sender: TObject);
begin
// 4-digit year
DateTime_SetFormat(DateTimePickerDate.Handle, pChar('M-dd-yyy'));
// 24-hour clock
DateTime_SetFormat(DateTimePickerTime.Handle, pChar('H:mm:ss'));
end;
|
See additional information about TDateTimePicker on the Delphi Dates and Times page.
A ShellExecute call is used to place a hyperlink to the Computer Lab on the Setup screen:
USES ShellAPI; // ShellExecute procedure TFormSetup.LabelLab2Click(Sender: TObject);
begin
ShellExecute(0, 'open', pchar('http://www.efg2.com/Lab'), NIL, NIL, SW_NORMAL)
end;
|
For the remaining details of this program, study the source code.
Conclusions
"Till" is a great utility for any clock watcher.
Keywords
TTimer, Now, TDateTime, TDateTimePicker, DateTime_SetFormat, Application.OnRestore,
Application.OnMinimize, Application.Title, Format, ClientWidth, ClientHeight, Trunc, Frac,
DecodeTime, EncodeDate, TIniFile, WritePrivateProfileString, ShellExecute
Download
Delphi 3/4/5 Source and EXE (141 KB): Till.ZIP
Updated 27 Nov 2002
since 5 Dec 1999