{$mode objfpc} uses Crt, WinCrt, SysUtils, DateUtils, Graph; const CX: Integer = 0; { getMaxX div 2} CY: Integer = 0; { getMaxY div 2} type TArrowType = ( { тип стрелки } atHour, { часовая } atMinute, { минутная } atSecond { секундная } ); const CArrowLength : array [TArrowType] of Single = ( 0.70, 0.85, 0.95 ); { коэфф. который будет умножен на радиус окружности, для получения длины стрелки (для часовой стрелки _length = 0.6 * Radius ) } CArrowAngles : array [TArrowType] of Single = ( 30.0, 6.0, 6.0 ); { количество градусов в одном делении для каждого вида стрелок } type TArrow = class { класс - стрелка } public constructor Create(const type_: TArrowType; const color_: Byte; const cRadius: Word); destructor Destroy; procedure GetNewCoords; { получение новых координат } procedure Show(const visible: Boolean); private _type: TArrowType; { тип стрелки } _color: Byte; { цвет стрелки } _length: Single; { длина стрелки, зависит от типа } currX, currY: Word; { текущие координаты конца стрелки } end; TClock = class constructor Create(const radius: Word); procedure Run; destructor Destroy; procedure DrawClock; private h, m, s: TArrow; _radius: Word; end; function GetRad(const angle: Single): Single; { перевод градусов в радианы } begin result := angle * (Pi / 180) end; constructor TArrow.Create(const type_: TArrowType; const color_: Byte; const cRadius: Word); begin _type := type_; _color := color_; _length := cRadius * CArrowLength[_type]; currX := 0; currY := 0; end; destructor TArrow.Destroy; begin end; procedure TArrow.GetNewCoords; var time: Word; begin case _type of atHour : time := HourOf(Now); atMinute : time := MinuteOf(Now); atSecond : time := SecondOf(Now); end; CurrX := cx + Round(_length * cos(GetRad(270 + time * CArrowAngles[_type]))); {+some} CurrY := cy + Round(_length * sin(GetRad(270 + time * CArrowAngles[_type]))); {+some} end; procedure TArrow.Show(const visible: Boolean); begin if visible then begin GetNewCoords; SetColor(_color); end else SetColor(GetBkColor); Line(CX, CY, CurrX, CurrY); Line(CX - 5, CY - 5, CurrX, CurrY); Line(CX + 5, CY + 5, CurrX, CurrY); end; procedure GrOpen; var gD, gM, gE: SmallInt; begin gD := Detect; InitGraph(gD, gM, ''); gE := GraphResult; if gE <> grOk then begin writeln('Can''t open graph mode, reason: ', GraphErrorMsg(gE)); readkey; Halt(1); end; CX := getMaxX div 2; CY := getMaxY div 2; end; constructor TClock.Create(const radius: Word); begin _radius := radius; h := TArrow.Create(atHour, Green, _radius); m := TArrow.Create(atMinute, Red, _radius); s := TArrow.Create(atSecond, Yellow, _radius); end; destructor TClock.Destroy; begin h.Destroy; m.Destroy; s.Destroy; end; procedure TClock.DrawClock; var ang, _cx, _cy: Word; begin Circle(cx, cy, _radius); ang := 0; while (ang < 360) do begin _cx := cx + round(_radius * SIN(GetRad(ang))); _cy := cy + round(_radius * COS(GetRad(ang))); if ang mod 30 = 0 then begin SetFillStyle(SolidFill, Red); FillEllipse(_cx, _cy, 6, 6); OutTextXY( cx + round((30 + _radius) * SIN(GetRad(180 - ang))), cy + round((30 + _radius) * COS(GetRad(180 - ang))), IntToStr(ang div 30) ) end else begin SetFillStyle(SolidFill, Blue); FillEllipse(_cx, _cy, 2, 2); end; inc(ang, 6); end; end; procedure TClock.Run; begin DrawClock; repeat h.Show(true); m.Show(true); s.Show(true); Delay(1000); h.Show(false); m.Show(false); s.Show(false); until keypressed; end; procedure GrClose; begin CloseGraph; end; begin GrOpen; with TClock.Create(200) do try Run; finally Destroy; end; GrClose; end.