dtanalogclock.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // SPDX-License-Identifier: LGPL-3.0-linking-exception
  2. {
  3. Part of BGRA Controls. Made by third party.
  4. For detailed information see readme.txt
  5. Site: https://sourceforge.net/p/bgra-controls/
  6. Wiki: http://wiki.lazarus.freepascal.org/BGRAControls
  7. Forum: http://forum.lazarus.freepascal.org/index.php/board,46.0.html
  8. }
  9. {******************************* CONTRIBUTOR(S) ******************************
  10. - Edivando S. Santos Brasil | [email protected]
  11. (Compatibility with delphi VCL 11/2018)
  12. ***************************** END CONTRIBUTOR(S) *****************************}
  13. unit DTAnalogClock;
  14. {$I bgracontrols.inc}
  15. interface
  16. uses
  17. Classes, SysUtils, {$IFDEF FPC}LResources,{$ENDIF}
  18. Forms, Controls, Graphics, Dialogs, ExtCtrls,
  19. {$IFNDEF FPC}Types, BGRAGraphics, GraphType, FPImage, {$ENDIF}
  20. BCBaseCtrls, BGRABitmap, BGRABitmapTypes, BGRAGradients;
  21. type
  22. TClockStyle = (stlBlue, stlGreen, stlWhite);
  23. { TDTCustomAnalogClock }
  24. TDTCustomAnalogClock = class(TBGRAGraphicCtrl)
  25. private
  26. FClockStyle: TClockStyle;
  27. FBitmap: TBGRABitmap;
  28. FClockFace: TBGRABitmap;
  29. FEnabled: boolean;
  30. FMovingParts: TBGRABitmap;
  31. FTimer: TTimer;
  32. FResized: boolean;
  33. procedure SetClockStyle(AValue: TClockStyle);
  34. { Private declarations }
  35. protected
  36. procedure SetEnabled(AValue: boolean); override;
  37. { Protected declarations }
  38. procedure Paint; override;
  39. procedure DrawClock; virtual;
  40. procedure DrawClockFace; virtual;
  41. procedure DrawMovingParts; virtual;
  42. procedure SwitchTimer;
  43. procedure TimerEvent({%H-}Sender: TObject);
  44. procedure ResizeEvent({%H-}Sender: TObject);
  45. public
  46. { Public declarations }
  47. constructor Create(AOwner: TComponent); override;
  48. destructor Destroy; override;
  49. property Enabled: boolean read FEnabled write SetEnabled;// default False;
  50. end;
  51. TDTAnalogClock = class(TDTCustomAnalogClock)
  52. private
  53. { Private declarations }
  54. protected
  55. { Protected declarations }
  56. public
  57. { Public declarations }
  58. published
  59. { Published declarations }
  60. //property ClockStyle;
  61. property Enabled;
  62. end;
  63. {$IFDEF FPC}procedure Register;{$ENDIF}
  64. implementation
  65. { TDTCustomAnalogClock }
  66. constructor TDTCustomAnalogClock.Create(AOwner: TComponent);
  67. begin
  68. inherited Create(AOwner);
  69. OnResize := ResizeEvent;
  70. Width := 128;
  71. Height := 128;
  72. FBitmap := TBGRABitmap.Create;
  73. FClockFace := TBGRABitmap.Create;
  74. FMovingParts := TBGRABitmap.Create;
  75. FBitmap.SetSize(Width, Height);
  76. DrawClockFace;
  77. DrawMovingParts;
  78. FTimer := TTimer.Create(Self);
  79. FTimer.Interval := 1000;
  80. FTimer.Enabled := FEnabled;
  81. FTimer.OnTimer := TimerEvent;
  82. end;
  83. destructor TDTCustomAnalogClock.Destroy;
  84. begin
  85. FTimer.Enabled:=False;
  86. FTimer.OnTimer:=nil;
  87. FBitmap.Free;
  88. FClockFace.Free;
  89. FMovingParts.Free;
  90. inherited Destroy;
  91. end;
  92. procedure TDTCustomAnalogClock.DrawClock;
  93. begin
  94. end;
  95. procedure TDTCustomAnalogClock.DrawClockFace;
  96. var
  97. img: TBGRABitmap;
  98. A: integer;
  99. w, h, r, Xo, Yo, X, Y, Xt, Yt: integer;
  100. phong: TPhongShading;
  101. begin
  102. w := Width;
  103. h := Height;
  104. { Set center point }
  105. Xo := w div 2;
  106. Yo := h div 2;
  107. // Determine radius. If canvas is rectangular then r = shortest length w or h
  108. r := yo;
  109. if xo > yo then
  110. r := yo;
  111. if xo < yo then
  112. r := xo;
  113. img := TBGRABitmap.Create(w, h);
  114. // Draw Bitmap frame
  115. img.FillEllipseAntialias(Xo, Yo, r * 0.99, r * 0.99, BGRA(175, 175, 175));
  116. // Draw Rounded/RIng type border using shading
  117. phong := TPhongShading.Create;
  118. phong.LightPosition := point(Xo, Yo);
  119. phong.DrawSphere(img, rect(round(Xo - r * 0.98), round(Yo - r * 0.98), round(Xo + r * 0.98) + 1, round(Yo + r * 0.98) + 1), 4, BGRA(245, 245, 245));
  120. phong.Free;
  121. img.EllipseAntialias(Xo, Yo, r * 0.99, r * 0.99, ColorToBGRA(clBlack, 110), 1);
  122. img.FillEllipseLinearColorAntialias(Xo, Yo, r * 0.88, r * 0.88, BGRA(0, 58, 81), BGRA(2, 94, 131));
  123. // Draw Face frame
  124. img.FillEllipseAntialias(Xo, Yo, r * 0.90, r * 0.90, BGRA(175, 175, 175));
  125. // Draw face background
  126. img.FillEllipseLinearColorAntialias(Xo, Yo, r * 0.88, r * 0.88, BGRA(0, 58, 81), BGRA(2, 94, 131));
  127. // Draw Bitmap face
  128. for A := 1 to 12 do
  129. begin
  130. X := Xo + Round(r * 0.80 * sin(30 * A * Pi / 180));
  131. Y := Yo - Round(r * 0.80 * cos(30 * A * Pi / 180));
  132. Xt := Xo + Round(r * 0.70 * sin(30 * A * Pi / 180));
  133. Yt := Yo - Round(r * 0.70 * cos(30 * A * Pi / 180));
  134. img.EllipseAntialias(x, y, (r * 0.02), (r * 0.02), BGRA(255, 255, 255, 200), 2, BGRA(2, 94, 131));
  135. img.FontName := 'Calibri';
  136. img.FontHeight := r div 8;
  137. img.FontQuality := fqFineAntialiasing;
  138. img.TextOut(Xt, Yt - (img.FontHeight / 1.7), IntToStr(A), BGRA(245, 245, 245), taCenter);
  139. end;
  140. FClockFace.Fill(BGRA(0, 0, 0, 0));
  141. FClockFace.Assign(img);
  142. img.Free;
  143. end;
  144. procedure TDTCustomAnalogClock.DrawMovingParts;
  145. var
  146. img: TBGRABitmap;
  147. w, h, r, Xo, Yo: integer;
  148. Xs, Ys, Xm, Ym, Xh, Yh: integer;
  149. th, tm, ts, tn: word;
  150. begin
  151. w := Width;
  152. h := Height;
  153. { Set center point }
  154. Xo := w div 2;
  155. Yo := h div 2;
  156. // Determine radius. If canvas is rectangular then r = shortest length w or h
  157. r := yo;
  158. if xo > yo then
  159. r := yo;
  160. if xo < yo then
  161. r := xo;
  162. //// Convert current time to integer values
  163. decodetime(Time, th, tm, ts, tn);
  164. //{ Set coordinates (length of arm) for seconds }
  165. Xs := Xo + Round(r * 0.78 * Sin(ts * 6 * Pi / 180));
  166. Ys := Yo - Round(r * 0.78 * Cos(ts * 6 * Pi / 180));
  167. //{ Set coordinates (length of arm) for minutes }
  168. Xm := Xo + Round(r * 0.68 * Sin(tm * 6 * Pi / 180));
  169. Ym := Yo - Round(r * 0.68 * Cos(tm * 6 * Pi / 180));
  170. //{ Set coordinates (length of arm) for hours }
  171. Xh := Xo + Round(r * 0.50 * Sin((th * 30 + tm / 2) * Pi / 180));
  172. Yh := Yo - Round(r * 0.50 * Cos((th * 30 + tm / 2) * Pi / 180));
  173. img := TBGRABitmap.Create(w, h);
  174. // Draw time hands
  175. img.DrawLineAntialias(xo, yo, xs, ys, BGRA(255, 0, 0), r * 0.02);
  176. img.DrawLineAntialias(xo, yo, xm, ym, BGRA(245, 245, 245), r * 0.03);
  177. img.DrawLineAntialias(xo, yo, xh, yh, BGRA(245, 245, 245), r * 0.07);
  178. img.DrawLineAntialias(xo, yo, xh, yh, BGRA(2, 94, 131), r * 0.04);
  179. // Draw Bitmap centre dot
  180. img.EllipseAntialias(Xo, Yo, r * 0.04, r * 0.04, BGRA(245, 245, 245, 255), r * 0.02, BGRA(210, 210, 210, 255));
  181. // Clear bitmap first
  182. FMovingParts.Fill(BGRA(0, 0, 0, 0));
  183. FMovingParts.Assign(img);
  184. img.Free;
  185. end;
  186. procedure TDTCustomAnalogClock.SwitchTimer;
  187. begin
  188. FTimer.Enabled := Enabled;
  189. end;
  190. procedure TDTCustomAnalogClock.Paint;
  191. begin
  192. inherited Paint;
  193. FBitmap.SetSize(Width, Height);
  194. FBitMap.Fill(BGRA(0, 0, 0, 0));
  195. if FResized then
  196. begin
  197. DrawClockFace;
  198. DrawMovingParts;
  199. FResized := False;
  200. end;
  201. FBitmap.BlendImage(0, 0, FClockFace, boLinearBlend);
  202. FBitmap.BlendImage(0, 0, FMovingParts, boLinearBlend);
  203. FBitmap.Draw(Canvas, 0, 0, False);
  204. end;
  205. procedure TDTCustomAnalogClock.ResizeEvent(Sender: TObject);
  206. begin
  207. FResized := True;
  208. end;
  209. procedure TDTCustomAnalogClock.SetClockStyle(AValue: TClockStyle);
  210. begin
  211. if FClockStyle = AValue then
  212. Exit;
  213. FClockStyle := AValue;
  214. end;
  215. procedure TDTCustomAnalogClock.SetEnabled(AValue: boolean);
  216. begin
  217. if FEnabled = AValue then
  218. Exit;
  219. FEnabled := AValue;
  220. SwitchTimer;
  221. end;
  222. procedure TDTCustomAnalogClock.TimerEvent(Sender: TObject);
  223. begin
  224. DrawMovingParts;
  225. Refresh;
  226. end;
  227. {$IFDEF FPC}
  228. procedure Register;
  229. begin
  230. RegisterComponents('BGRA Controls', [TDTAnalogClock]);
  231. end;
  232. {$ENDIF}
  233. end.