home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows 95 / Programming Windows 95.iso / code / CHAP07 / ANACLOCK.C next >
Encoding:
C/C++ Source or Header  |  1996-01-01  |  5.9 KB  |  199 lines

  1. /*-----------------------------------------
  2.    ANACLOCK.C -- Analog Clock Program
  3.                  (c) Charles Petzold, 1996
  4.   -----------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <string.h>
  8. #include <time.h>
  9. #include <math.h>
  10.  
  11. #define ID_TIMER    1
  12. #define TWOPI       (2 * 3.14159)
  13.  
  14. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  15.  
  16. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  17.                     PSTR szCmdLine, int iCmdShow)
  18.      {
  19.      static char szAppName[] = "AnaClock" ;
  20.      HWND        hwnd;
  21.      MSG         msg;
  22.      WNDCLASSEX  wndclass ;
  23.  
  24.      wndclass.cbSize        = sizeof (wndclass) ;
  25.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  26.      wndclass.lpfnWndProc   = WndProc ;
  27.      wndclass.cbClsExtra    = 0 ;
  28.      wndclass.cbWndExtra    = 0 ;
  29.      wndclass.hInstance     = hInstance ;
  30.      wndclass.hIcon         = NULL ;
  31.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  32.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  33.      wndclass.lpszMenuName  = NULL ;
  34.      wndclass.lpszClassName = szAppName ;
  35.      wndclass.hIconSm       = NULL ;
  36.  
  37.      RegisterClassEx (&wndclass) ;
  38.  
  39.      hwnd = CreateWindow (szAppName, "Analog Clock",
  40.                           WS_OVERLAPPEDWINDOW,
  41.                           CW_USEDEFAULT, CW_USEDEFAULT,
  42.                           CW_USEDEFAULT, CW_USEDEFAULT,
  43.                           NULL, NULL, hInstance, NULL) ;
  44.  
  45.      if (!SetTimer (hwnd, ID_TIMER, 1000, NULL))
  46.           {
  47.           MessageBox (hwnd, "Too many clocks or timers!", szAppName,
  48.                       MB_ICONEXCLAMATION | MB_OK) ;
  49.           return FALSE ;
  50.           }
  51.  
  52.      ShowWindow (hwnd, iCmdShow) ;
  53.      UpdateWindow (hwnd) ;
  54.  
  55.      while (GetMessage (&msg, NULL, 0, 0))
  56.           {
  57.           TranslateMessage (&msg) ;
  58.           DispatchMessage (&msg) ;
  59.           }
  60.      return msg.wParam ;
  61.      }
  62.  
  63. void SetIsotropic (HDC hdc, int cxClient, int cyClient)
  64.      {
  65.      SetMapMode (hdc, MM_ISOTROPIC) ;
  66.      SetWindowExtEx (hdc, 1000, 1000, NULL) ;
  67.      SetViewportExtEx (hdc, cxClient / 2, -cyClient / 2, NULL) ;
  68.      SetViewportOrgEx (hdc, cxClient / 2,  cyClient / 2, NULL) ;
  69.      }
  70.  
  71. void RotatePoint (POINT pt[], int iNum, int iAngle)
  72.      {
  73.      int   i ;
  74.      POINT ptTemp ;
  75.  
  76.      for (i = 0 ; i < iNum ; i++)
  77.           {
  78.           ptTemp.x = (int) (pt[i].x * cos (TWOPI * iAngle / 360) +
  79.                             pt[i].y * sin (TWOPI * iAngle / 360)) ;
  80.  
  81.           ptTemp.y = (int) (pt[i].y * cos (TWOPI * iAngle / 360) -
  82.                             pt[i].x * sin (TWOPI * iAngle / 360)) ;
  83.  
  84.           pt[i] = ptTemp ;
  85.           }
  86.      }
  87.  
  88. void DrawClock (HDC hdc)
  89.      {
  90.      int   iAngle ;
  91.      POINT pt[3] ;
  92.  
  93.      for (iAngle = 0 ; iAngle < 360 ; iAngle += 6)
  94.           {
  95.           pt[0].x =   0 ;
  96.           pt[0].y = 900 ;
  97.  
  98.           RotatePoint (pt, 1, iAngle) ;
  99.  
  100.           pt[2].x = pt[2].y = iAngle % 5 ? 33 : 100 ;
  101.  
  102.           pt[0].x -= pt[2].x / 2 ;
  103.           pt[0].y -= pt[2].y / 2 ;
  104.  
  105.           pt[1].x  = pt[0].x + pt[2].x ;
  106.           pt[1].y  = pt[0].y + pt[2].y ;
  107.  
  108.           SelectObject (hdc, GetStockObject (BLACK_BRUSH)) ;
  109.  
  110.           Ellipse (hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y) ;
  111.           }
  112.      }
  113.  
  114. void DrawHands (HDC hdc, struct tm *datetime, BOOL bChange)
  115.      {
  116.      static POINT pt[3][5] = { 0, -150, 100, 0, 0, 600, -100, 0, 0, -150,
  117.                                0, -200,  50, 0, 0, 800,  -50, 0, 0, -200,
  118.                                0,    0,   0, 0, 0,   0,    0, 0, 0,  800 } ;
  119.      int          i, iAngle[3] ;
  120.      POINT        ptTemp[3][5] ;
  121.  
  122.      iAngle[0] = (datetime->tm_hour * 30) % 360 + datetime->tm_min / 2 ;
  123.      iAngle[1] =  datetime->tm_min  *  6 ;
  124.      iAngle[2] =  datetime->tm_sec  *  6 ;
  125.  
  126.      memcpy (ptTemp, pt, sizeof (pt)) ;
  127.  
  128.      for (i = bChange ? 0 : 2 ; i < 3 ; i++)
  129.           {
  130.           RotatePoint (ptTemp[i], 5, iAngle[i]) ;
  131.  
  132.           Polyline (hdc, ptTemp[i], 5) ;
  133.           }
  134.      }
  135.  
  136. LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  137.      {
  138.      static int         cxClient, cyClient ;
  139.      static struct tm   dtPrevious ;
  140.      BOOL               bChange ;
  141.      HDC                hdc ;
  142.      PAINTSTRUCT        ps ;
  143.      time_t             lTime ;
  144.      struct tm         *datetime ;
  145.  
  146.      switch (iMsg)
  147.           {
  148.           case WM_CREATE :
  149.                time (&lTime) ;
  150.                datetime = localtime (&lTime) ;
  151.  
  152.                dtPrevious = * datetime ;
  153.                return 0 ;
  154.  
  155.           case WM_SIZE :
  156.                cxClient = LOWORD (lParam) ;
  157.                cyClient = HIWORD (lParam) ;
  158.                return 0 ;
  159.  
  160.           case WM_TIMER :
  161.                time (&lTime) ;
  162.                datetime = localtime (&lTime) ;
  163.  
  164.                bChange = datetime->tm_hour != dtPrevious.tm_hour ||
  165.                          datetime->tm_min  != dtPrevious.tm_min ;
  166.  
  167.                hdc = GetDC (hwnd) ;
  168.  
  169.                SetIsotropic (hdc, cxClient, cyClient) ;
  170.  
  171.                SelectObject (hdc, GetStockObject (WHITE_PEN)) ;
  172.                DrawHands (hdc, &dtPrevious, bChange) ;
  173.  
  174.                SelectObject (hdc, GetStockObject (BLACK_PEN)) ;
  175.                DrawHands (hdc, datetime, TRUE) ;
  176.  
  177.                ReleaseDC (hwnd, hdc) ;
  178.  
  179.                dtPrevious = *datetime ;
  180.                return 0 ;
  181.  
  182.           case WM_PAINT :
  183.                hdc = BeginPaint (hwnd, &ps) ;
  184.  
  185.                SetIsotropic (hdc, cxClient, cyClient) ;
  186.                DrawClock    (hdc) ;
  187.                DrawHands    (hdc, &dtPrevious, TRUE) ;
  188.  
  189.                EndPaint (hwnd, &ps) ;
  190.                return 0 ;
  191.  
  192.           case WM_DESTROY :
  193.                KillTimer (hwnd, ID_TIMER) ;
  194.                PostQuitMessage (0) ;
  195.                return 0 ;
  196.           }
  197.      return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
  198.      }
  199.