(Connected to above)
Component's code is assumed that you are already familiar with Delphi development (it's nothing different from the general development), we will put it directly and add appropriate annotations:
Unit clock;
Interface
Uses
Sysutils, Classes, Controls, Stdctrls, ExtCtrls;
Type
TSTATE = (stclock, strunclock, stqueck); // Define the 3 states of the enumeration class representation: clock, running table, countdown clock
Tclock = Class (TCUSTOMLABEL)
Private
FSTATE: TSTATE;
ftimer: TTIMER; // Why use this component as a private member of our components, you don't have to say it.
RCD: Array [1..8] of integer; // Various digits in the running table.
Fbegintime: String; // When the timing is started, the reason why the TTIME type is not used to demonstrate the attribute editor
Fwaketime: String; // Alarm Time, the same reason for the above
FallowWake: Boolean; / / Do you turn on alarm function
Fonwakeup: TNOTIFYEVENT; / / In order to make the components more perfect, we allow component users to respond to time when the alarm arrival
Fontimeup: TNOTIFYEVENT; // We can respond to events when completed by countdown, we will release these two events
Function getActive: boolean; / / Control whether Timer works to control the three states
Procedure setActive (Value: Boolean);
Procedure setState (Value: tState);
Procedure setBegintime (Value: string);
Procedure setwaketime (value: string);
protected
Procedure Walkclock (Sender: TOBJECT); / / Event for a clock
Procedure Runclock (Sender: TOBJECT); // Runfark
Procedure BackClock (Sender: TOBJECT); // Countdown
public
Constructor Create (Aowner: Tcomponent); Override; // Complete some initialization work
Procedure reSetrunClock; // Run table and countdown need a reset method to the component user call
Procedure resetBackClock;
Published
Property State: TState Read FState Write SetState Default attlock; // Default is a clock state
Property Active: Boolean Read GetActive Write SetACTIVE; // Controls if the 3 states are working
Property Begintime: String Read Fbegintime Write setBegintime;
Property Waketime: String Read Fwaketime Write SetwakeTime;
Property AllowWake: Boolean Read Fallowwake Write Fallowwake;
Property OnWakeup: TNOTIFYEVENT Read Fonwakeup Write Fonwakeup;
Property Ontimeup: TNotifyEvent Read Fontimeup Write Fontimeup;
// Finally, we release some attributes hidden by TCUSTOMLABEL and we need.
Property Align;
Property alignment;
Property Color;
Property font;
Property ParentColor; Property ParentFont;
Property Parentshowhint;
Property Popupmenu;
Property Showhint;
Property visible;
Property Transparent;
Property Onclick;
END;
PROCEDURE register;
IMPLEMENTATION
PROCEDURE register;
Begin
Registercomponents ('ClockandTime', [TCLOCK]);
END;
{Tclock}
Constructor Tclock.create (Aowner: Tcomponent);
Begin
Inherited Create (Aowner);
/ / Set the default value
ftimer: = TTIMER.CREATE (Self);
// Take it to our components, so you don't have to write a destructor, and you can release Timer when you release this component.
Active: = FALSE;
AllowWake: = false;
State: = stclock;
Begintime: = '00:00:00';
WAKETIME: = '00:00:00';
END;
Function Tclock.getActive: boolean;
Begin
Result: = ftimer.enable;
END;
Procedure Tclock.setAntActive (Value: Boolean);
Begin
ftimer.enabled: = value;
END;
Procedure Tclock.setState (Value: TSTATE);
VAR
i: integer;
Begin
Case Value of
STCLOCK:
Begin
Active: = FALSE;
ftimer.Interval: = 1000;
ftimer.ontimer: = WalkClock;
Active: = True;
END;
Strunclock: // Due to the Time type is not good to process microsecond operation, we only manually imitate this operation, the code will be slightly cumbersome
Begin
Active: = FALSE;
For i: = 1 to 8 DO RCD [I]: = 0;
CAPTION: = INTOSTR (RCD [8]) INTSTR (RCD [7]) ':' INTOSTR (RCD [6]) INTOSTR (RCD [5]) ':' INTOSTR (RCD [4]) ;
CAPTION: = CAPTION INTOSTR (RCD [3]) ':' INTOSTR (RCD [2]) INTOSTR (RCD [1]);
ftimer.Interval: = 10;
// Test, this stopwatch is very good, but this is just a technical demonstration.
// In fact, this continuous execution of such frequent (1/100 seconds) will make the CPU's occupation of 100%
// This is not a good attention. In fact, we must want to display microsecond levels in the running table and make a reasonable occupation CPU.
// This requires more flexible and complex programming
ftimer.ontimer: = Runclock;
END;
StBackClock:
Begin
Active: = FALSE;
Caption: = begintime;
ftimer.Interval: = 1000;
ftimer.ontimer: = backclock;
END;
END;
FSTATE: = value;
END;
Procedure Tclock.setBegintime (Value: String);
Begin
Try
Strtotime (Value);
Fbeggintime: = value;
If state = stqueckclock dam
Begin
Active: = FALSE;
Caption: = value;
END;
Except
ON Exception DO
Begin
Fbeggintime: = '00:00:00';
if State = StBackClock Then Caption: = '00:00:00';
END;
END;
END;
Procedure Tclock.SetwakeTime (value: string);
Begin
Try
Strtotime (Value);
Fwaketime: = value;
Except
ON Exception DO
Begin
Fwaketime: = '00:00:00';
END;
END;
END;
Procedure Tclock.walkclock (Sender: TOBJECT);
Begin
CAPTION: = Timetostr (Time);
IF allowwake and (strtotime (caption) = strtotime (waketime)) THEN
Begin
BEEP; // buzzer
IF assigned (fonwakeup) THEN
Fonwakeup (Self);
END;
END;
Procedure Tclock.Runclock (Sender: TOBJECT);
Begin
RCD [1]: = RCD [1] 1;
IF rcd [1] = 10 THEN Begin RCD [2]: = RCD [2] 1; RCD [1]: = 0;
IF RCD [2] = 10 THEN Begin RCD [3]: = RCD [3] 1; RCD [2]: = 0;
IF RCD [3] = 10 THEN BEGIN RCD [4]: = RCD [4] 1; RCD [3]: = 0;
IF RCD [4] = 6 Then Begin RCD [5]: = RCD [5] 1; RCD [4]: = 0;
IF RCD [5] = 10 Then Begin RCD [6]: = RCD [6] 1; RCD [5]: = 0;
IF RCD [6] = 6 THEN Begin RCD [7]: = RCD [7] 1; RCD [6]: = 0;
IF RCD [7] = 10 THEN Begin RCD [8]: = RCD [8] 1; RCD [7]: = 0;
IF RCD [8] = 10 THEN RCD [8]: = 0; // Our running gates can be worth 99 hours;
CAPTION: = INTOSTR (RCD [8]) INTSTR (RCD [7]) ':' INTOSTR (RCD [6]) INTOSTR (RCD [5]) ':' INTOSTR (RCD [4]) ;
CAPTION: = CAPTION INTOSTR (RCD [3]) ':' INTOSTR (RCD [2]) INTOSTR (RCD [1]);
END;
Procedure Tclock.backclock (Sender: Tobject); // Begin can be taken down on time in one day
If stratotime (caption) <> stratime ('00: 00: 00') THEN
CAPTION: = Timetostr (STRTOTIME (CAPTION) -0.00001)
Else
Begin
Active: = FALSE;
BEEP;
IF assigned (fontimeup) THEN
Fontimeup (Self);
END;
END;
Procedure Tclock.resetBackClock;
VAR
i: integer;
Begin
If state = strunclock then
Begin
Active: = FALSE;
For i: = 1 to 8 DO RCD [I]: = 0;
CAPTION: = '00: 00: 00: 00';
END;
END;
Procedure tclock.resetrunclock;
Begin
If state = stqueckclock dam
Begin
Active: = FALSE;
Caption: = begintime;
END;
END;
End.
In order to test our components, you can now install this component package and create an app to test it, click on the install in the component package form (Note: One but you installed the component package, when you want to modify the component After modifying the original code, you can update the component with only the Compile of the Component Form. At this time, the finals of the Delphi's component page has made our definition page, which has our components!
However, this component is still not perfect so far, and it is not officially released to the user. In the next article we will solve two important problems: 1. Add a default icon to our components. 2. Classify this component messy attribute.
(Endlessly)