home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 1995 December / SOFM_Dec1995.bin / pc / os2 / vpascal / examples / clock / clock.pas
Pascal/Delphi Source File  |  1995-10-31  |  7KB  |  254 lines

  1. {█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█}
  2. {█                                                       █}
  3. {█      Virtual Pascal Examples. Version 1.0.            █}
  4. {█      Presentation Manager analog clock example        █}
  5. {█      ─────────────────────────────────────────────────█}
  6. {█      Written by Vitaly Miryanov                       █}
  7. {█      ─────────────────────────────────────────────────█}
  8. {█      Copyright (C) 1995 B&M&T Corporation             █}
  9. {█                                                       █}
  10. {▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀}
  11.  
  12. program Clock;
  13.  
  14. uses Os2Def, Os2Base, Os2PmApi, PmObj, Use32;
  15.  
  16. {$IFDEF DYNAMIC_VERSION}
  17.   {$Dynamic System }
  18.   {$L VPRTL.LIB}
  19. {$ENDIF}
  20.  
  21. const
  22.   idTimer       = 1;            { PM timer id }
  23.  
  24. const
  25.   ClockFlags = fcf_TitleBar + fcf_SysMenu + fcf_SizeBorder + fcf_MinMax +
  26.                fcf_TaskList + fcf_NoByteAlign;
  27.  
  28. type
  29.   PClockWindow = ^TClockWindow;
  30.   TClockWindow = object(PMWindow)
  31.     PS: HPS;
  32.     PixelDiam: PointL;
  33.     ClientSize: PointL;
  34.     PixelsPerMeter: PointL;
  35.     DTPrev: DateTime;
  36.     procedure DrawHand(AP: array of PointL; Angle: Integer);
  37.     function HandleMessage(Window: HWnd; Msg: ULong; Mp1,Mp2 : MParam): MResult; virtual;
  38.     procedure RotateFigure(var AP: array of PointL; Angle: Integer);
  39.     procedure ScaleFigure(var AP: array of PointL);
  40.     procedure StartupAction; virtual;
  41.     procedure CenterFigure(var AP: array of PointL);
  42.   end;
  43.  
  44.   ClockApplication = object(PMApplication)
  45.     MainWindow: PClockWindow;
  46.     constructor Init;
  47.     destructor Done; virtual;
  48.   end;
  49.  
  50. { Return the smaller of two integer values }
  51.  
  52. function Min(X, Y: Integer): Integer;
  53. begin
  54.   if X < Y then Min := X else Min := Y;
  55. end;
  56.  
  57. { ClockApplication }
  58.  
  59. constructor ClockApplication.Init;
  60. begin
  61.   inherited Init;
  62.   MainWindow := New(PClockWindow, Init('VP Clock', 'Clock', ClockFlags));
  63. end;
  64.  
  65. destructor ClockApplication.Done;
  66. begin
  67.   Dispose(MainWindow, Done);
  68.   inherited Done;
  69. end;
  70.  
  71. { TClockWindow }
  72.  
  73. procedure TClockWindow.StartupAction;
  74. var
  75.   Size: Integer;
  76. begin
  77.   WinStartTimer(Anchor, ClientWindow, idTimer, 1000);
  78.   Size := Min(DesktopSize.X div 3, DesktopSize.Y div 3);
  79.   WinSetWindowPos(FrameWindow, 0, DesktopSize.X - Size, DesktopSize.Y - Size,
  80.     Size, Size, swp_Move + swp_Size + swp_Activate + swp_Show);
  81. end;
  82.  
  83. { Handles PM messages }
  84.  
  85. function TClockWindow.HandleMessage(Window: HWnd; Msg: ULong; Mp1,Mp2: MParam): MResult;
  86. var
  87.   DC: HDC;
  88.   DiamMM, Angle, I: Integer;
  89.   AP: array [0..2] of PointL;
  90.   DT: DateTime;
  91. const
  92.   Hour:   array [0..4] of PointL = ((X:0; Y:-15), (X:7; Y:0 ), (X:0; Y:60), (X:-7; Y:0), (X:0;Y:-15));
  93.   Minute: array [0..4] of PointL = ((X:0; Y:-20), (X:5 ; Y:0), (X:0; Y:80), (X:-5; Y:0), (X:0;Y:-20));
  94.   Second: array [0..1] of PointL = ((X:0; Y:0  ), (X:0; Y:80));
  95.   BigCycle: array [0..1] of Integer = (10, 8);
  96. begin
  97.   HandleMessage := 0;
  98.   case Msg of
  99.     wm_Create:
  100.       begin
  101.         DC := WinOpenWindowDC(Window);
  102.         DevQueryCaps(DC, caps_Vertical_Resolution,   1, PixelsPerMeter.Y);
  103.         DevQueryCaps(DC, caps_Horizontal_Resolution, 1, PixelsPerMeter.X);
  104.         DosGetDateTime(DTPrev) ;
  105.         DTPrev.hours := (DTPrev.hours * 5) mod 60 + DTPrev.minutes div 12;
  106.       end;
  107.  
  108.     wm_Size:
  109.       begin
  110.         ClientSize.X := LongRec(Mp2).Lo;
  111.         ClientSize.Y := LongRec(Mp2).Hi;
  112.         DiamMM := Min(ClientSize.X * 1000 div PixelsPerMeter.X,
  113.                       ClientSize.Y * 1000 div PixelsPerMeter.Y);
  114.         PixelDiam.X := PixelsPerMeter.X * DiamMM div 1000;
  115.         PixelDiam.Y := PixelsPerMeter.Y * DiamMM div 1000;
  116.       end;
  117.  
  118.     wm_Timer:
  119.       begin
  120.         DosGetDateTime(DT);
  121.         DT.hours := (DT.hours * 5) mod 60 + DT.minutes div 12;
  122.         PS := WinGetPS(Window);
  123.         GpiSetColor(PS, clr_Background);
  124.         DrawHand(Second, DTPrev.seconds);
  125.         if (DT.hours <> DTPrev.hours) or (DT.minutes <> DTPrev.minutes) then
  126.         begin
  127.           DrawHand(Hour, DTPrev.hours);
  128.           DrawHand(Minute, DTPrev.minutes);
  129.         end;
  130.         GpiSetColor(PS, clr_Darkgray);
  131.         DrawHand(Hour, DT.hours);
  132.         DrawHand(Minute, DT.minutes);
  133.         DrawHand(Second, DT.seconds);
  134.         WinReleasePS(PS);
  135.         DTPrev := DT;
  136.       end;
  137.  
  138.     wm_Paint:
  139.       begin
  140.         PS := WinBeginPaint(Window, 0, nil);
  141.         GpiErase(PS);
  142.         for Angle := 0 to 59 do
  143.         begin
  144.           I := 0;
  145.           repeat
  146.             if I = 1 then GpiSetColor(PS, clr_Darkcyan) else GpiSetColor(PS, clr_Black);
  147.             AP[0].X := 0;
  148.             AP[0].Y := 90;
  149.             RotateFigure(AP[0], Angle);
  150.             ScaleFigure(AP[0]);
  151.             CenterFigure(AP[0]);
  152.             if (Angle mod 5) <> 0 then AP[2].X := 2 else AP[2].X := BigCycle[I];
  153.             AP[2].Y := AP[2].X;
  154.             ScaleFigure(AP[2]);
  155.             Dec(AP[0].X, AP[2].X div 2);
  156.             Dec(AP[0].Y, AP[2].Y div 2);
  157.             AP[1].X := AP[0].X + AP[2].X;
  158.             AP[1].Y := AP[0].Y + AP[2].Y;
  159.             GpiMove(PS, AP[0]);
  160.             GpiBox(PS, dro_OutlineFill, AP[1], AP[2].X, AP[2].Y);
  161.             Inc(I);
  162.           until ((Angle mod 5) <> 0) or (I = 2);
  163.         end;
  164.         GpiSetColor(PS, clr_Darkgray);
  165.         DrawHand(Hour, DTPrev.hours);
  166.         DrawHand(Minute, DTPrev.minutes);
  167.         DrawHand(Second, DTPrev.seconds);
  168.         WinEndPaint(PS);
  169.       end;
  170.  
  171.      else HandleMessage := WinDefWindowProc(Window, Msg, Mp1, Mp2);
  172.    end;
  173. end;
  174.  
  175. { Rotates figure }
  176.  
  177. procedure TClockWindow.RotateFigure(var AP: array of PointL; Angle: Integer);
  178. const
  179.   SinTable: array [0..59] of SmallInt =
  180.     (   0,  105,  208,  309,  407,  500,  588,  669,  743,  809,
  181.       866,  914,  951,  978,  995, 1000,  995,  978,  951,  914,
  182.       866,  809,  743,  669,  588,  500,  407,  309,  208,  105,
  183.         0, -104, -207, -308, -406, -499, -587, -668, -742, -808,
  184.      -865, -913, -950, -977, -994, -999, -994, -977, -950, -913,
  185.      -865, -808, -742, -668, -587, -499, -406, -308, -207, -104
  186.     );
  187. var
  188.   P: PointL;
  189.   I: Integer;
  190. begin
  191.   for I := 0 to High(AP) do
  192.   with AP[I] do
  193.     begin
  194.       P.X := (X * SinTable[(Angle + 15) mod 60] +
  195.               Y * SinTable[Angle]) div 1000;
  196.       P.Y := (Y * SinTable[(Angle + 15) mod 60] -
  197.               X * SinTable[Angle]) div 1000;
  198.       AP[I] := P;
  199.     end;
  200. end;
  201.  
  202. { Scales figure }
  203.  
  204. procedure TClockWindow.ScaleFigure(var AP: array of PointL);
  205. var
  206.   I: Integer;
  207. begin
  208.   for I := 0 to High(AP) do
  209.     with AP[I] do
  210.     begin
  211.       X := X * PixelDiam.X div 200;
  212.       Y := Y * PixelDiam.Y div 200;
  213.     end;
  214. end;
  215.  
  216. { Centers figure on the client window }
  217.  
  218. procedure TClockWindow.CenterFigure(var AP: array of PointL);
  219. var
  220.   I: Integer;
  221. begin
  222.   for I := 0 to High(AP) do
  223.   with AP[I] do
  224.     begin
  225.       Inc(X, ClientSize.X div 2);
  226.       Inc(Y, ClientSize.Y div 2);
  227.     end;
  228. end;
  229.  
  230. { Draws watch hand }
  231.  
  232. procedure TClockWindow.DrawHand(AP: array of PointL; Angle: Integer);
  233. var
  234.   I: Integer;
  235. begin
  236.   RotateFigure(AP, Angle);
  237.   ScaleFigure(AP);
  238.   CenterFigure(AP);
  239.   GpiBeginPath(PS, 1);
  240.   GpiMove(PS, AP[0]);
  241.   GpiPolyLine(PS, High(AP), AP[1]);
  242.   GpiEndPath(PS);
  243.   GpiFillPath(PS, 1, fpath_Alternate);
  244. end;
  245.  
  246. var
  247.   AnalogClock: ClockApplication;
  248.  
  249. begin
  250.   AnalogClock.Init;
  251.   AnalogClock.Run;
  252.   AnalogClock.Done;
  253. end.
  254.