windows程序设计 之 「CLOCK」范例分析笔记

/*--------------------------------------
   CLOCK.C -- Analog Clock Program
              (c) Charles Petzold, 1998
  --------------------------------------*/


#include <windows.h>
#include <math.h>

#define ID_TIMER     1
#define TWOPI        (2 * 3.14159 )

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR   szAppName[] = TEXT ("Clock ") ;
     HWND             hwnd;
     MSG                msg;
     WNDCLASS     wndclass ;
    
     wndclass.style                   = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc       = WndProc ;
     wndclass.cbClsExtra          = 0 ;
     wndclass.cbWndExtra       = 0 ;
     wndclass.hInstance           = hInstance ;
     wndclass.hIcon                  = NULL ;
     wndclass.hCursor              = LoadCursor (NULL, IDC_ARROW ) ;
     wndclass.hbrBackground   = (HBRUSH) GetStockObject (WHITE_BRUSH ) ;
     wndclass.lpszMenuName   = NULL ;
     wndclass.lpszClassName   = szAppName ;
    
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT! "),
                      szAppName, MB_ICONERROR ) ;
          return 0 ;
     }
    
     hwnd = CreateWindow (szAppName, TEXT ("Analog Clock "),
                          WS_OVERLAPPEDWINDOW ,
                          CW_USEDEFAULT , CW_USEDEFAULT ,
                          CW_USEDEFAULT , CW_USEDEFAULT ,
                          NULL, NULL, hInstance, NULL) ;
    
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
    
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

void SetIsotropic (HDC hdc, int cxClient, int cyClient)
{    //使用同方向性映像模式
     SetMapMode (hdc, MM_ISOTROPIC ) ;
     //设置逻辑范围为1000,1000
     SetWindowExtEx (hdc, 1000, 1000, NULL) ;
     //设置设备范围
     SetViewportExtEx (hdc, cxClient / 2, -cyClient / 2, NULL) ;
     //设置设备原点为窗口中央。
     SetViewportOrgEx (hdc, cxClient / 2,  cyClient / 2, NULL) ;
     //该函数设定映像方式为 四象限笛卡尔坐标系 。
     //从窗口中心点开始,左-X ,右+X ,上+Y ,下-Y 。

}

void RotatePoint (POINT pt[], int iNum, int iAngle)
{
     int   i ;
     POINT ptTemp ;
    
     for (i = 0 ; i < iNum ; i++)
     {
         //TWOPI * iAngle / 360 转换角度为弧度。
         //Cos()=X/R  X坐标在半径中的比例
         //Sin() =Y/R   Y坐标在半径中的比例

         //该算法实现:将始边设为+Y轴,旋转方向为顺时针

         ptTemp.x = (int) (pt[i].x * cos (TWOPI * iAngle / 360) +
             pt[i].y * sin (TWOPI * iAngle / 360)) ;
         
          ptTemp.y = (int) (pt[i].y * cos (TWOPI * iAngle / 360) -
              pt[i].x * sin (TWOPI * iAngle / 360)) ;
         
         pt[i] = ptTemp ;
     }
}

void DrawClock (HDC hdc)
{
     int        iAngle ;
     POINT  pt[3] ;
    
     for (iAngle = 0 ; iAngle < 360 ; iAngle += 6)
     {
          pt[0].x =   0 ;
          pt[0].y = 900 ;  //矩形中心点
         
          RotatePoint (pt, 1, iAngle) ; //以6度为单位进行顺时针旋转
         
          pt[2].x = pt[2].y = iAngle % 5 ? 33 : 100 ; //判断设置圆点大小,以5为间隔。
         
          //假设要在12点画一个圆,圆大小为100.
          //pt[0].x = 0 - (100/2)   = -50      矩形左边
          //pt[0].y = 900-(100/2) = 850     矩形顶边
          //pt[1].x = -50 + 100     = 50      矩形右边
          //pt[1].y = 850 + 100    = 950    矩形底边

          pt[0].x -= pt[2].x / 2 ;
          pt[0].y -= pt[2].y / 2 ;
         
          pt[1].x  = pt[0].x + pt[2].x ;
          pt[1].y  = pt[0].y + pt[2].y ;
         
          SelectObject (hdc, GetStockObject (BLACK_BRUSH )) ;
         
          Ellipse (hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y) ; //在给定矩形内画圆
     }
}

void DrawHands (HDC hdc, SYSTEMTIME * pst, BOOL fChange)
{
     static POINT pt[3][5] = { 0, -150, 100, 0, 0, 600, -100, 0, 0, -150,       //时针12点时多边形坐标
                                             0, -200,   50, 0, 0, 800,   -50, 0, 0, -200,       //分针12点时多边形坐标
                                             0,    0,       0, 0,  0,   0,       0, 0,  0,  800 } ;  //秒针12点时绘画坐标
     int              i, iAngle[3] ;
     POINT        ptTemp[3][5] ;
    
     iAngle[0] = (pst->wHour * 30) % 360 + pst->wMinute / 2 ; //时针在坐标系里的对应角度
     iAngle[1] =  pst->wMinute  *  6 ; //分针角度
     iAngle[2] =  pst->wSecond  *  6 ; //秒针角度
    
     memcpy (ptTemp, pt, sizeof (pt)) ; //复制画笔坐标到临时数组
    
     for (i = fChange ? 0 : 2 ; i < 3 ; i++) //如果小时或分钟更改,i=0,否者等于2(意思是只画秒针)。
     {
          RotatePoint (ptTemp[i], 5, iAngle[i]) ; //根据角度,计算顺时针旋转后的坐标

          Polyline (hdc, ptTemp[i], 5) ;  //根据旋转后的坐标,画多边形(表针)
     }
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static int                  cxClient, cyClient ;
     static SYSTEMTIME   stPrevious ;
     BOOL                       fChange ;
     HDC                         hdc ;
     PAINTSTRUCT           ps ;
     SYSTEMTIME            st ;

     switch (message)
     {
     case WM_CREATE :
          SetTimer (hwnd, ID_TIMER, 1000, NULL) ;
          GetLocalTime (&st) ; //获取系统当前时间信息
          stPrevious = st ;       //保存窗口创建时的时间信息
          return 0 ;
         
     case WM_SIZE :
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;
          return 0 ;
         
     case WM_TIMER :
          GetLocalTime (&st) ;
         
          //判断小时或者分钟,是否有更改。
          fChange = st.wHour   != stPrevious.wHour ||
                           st.wMinute != stPrevious.wMinute ;
         
          hdc = GetDC (hwnd) ;
         
          SetIsotropic (hdc, cxClient, cyClient) ;//该函数设定映像方式为 四象限笛卡尔坐标系 。
         
          SelectObject (hdc, GetStockObject (WHITE_PEN)) ; //设置白色画笔
          DrawHands (hdc, &stPrevious, fChange) ;               //涂抹掉之前的表针
         
          SelectObject (hdc, GetStockObject (BLACK_PEN)) ;  //设置黑色画笔
          DrawHands (hdc, &st, TRUE) ;                                  //绘画当前表针
         
          ReleaseDC (hwnd, hdc) ;
         
          stPrevious = st ;   //保存时间信息,用于下次比较
          return 0 ;
         
     case WM_PAINT :
          hdc = BeginPaint (hwnd, &ps) ;
         
          SetIsotropic (hdc, cxClient, cyClient) ;      //该函数设定映像方式为 四象限笛卡尔坐标系。
          DrawClock     (hdc) ;                                  //绘画钟面圆点
          DrawHands     (hdc, &stPrevious, TRUE) ; //绘画当前表针
         
          EndPaint (hwnd, &ps) ;
          return 0 ;
         
     case WM_DESTROY :
          KillTimer (hwnd, ID_TIMER) ;
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值