模拟时钟

以下程序是书上的,只是加了一些自己的注释,方便理解

# include<windows.h>
# include<cmath>

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    PSTR lpCmdLine,
    int iCmdShow
    )
{
    TCHAR szAppName[] = TEXT("Clock");
    WNDCLASS wndclass;

    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//这里用NULL表示使用微软提供的图标
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //同上
    wndclass.hInstance = hInstance;
    wndclass.lpfnWndProc = WndProc;
    wndclass.lpszClassName = szAppName;
    wndclass.lpszMenuName = NULL;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    if (!RegisterClass(&wndclass))//注册窗口类
    {
        MessageBox(NULL, "Program requires windows NT!", szAppName, MB_ICONERROR);
        return 0;
    }

    HWND hwnd;
    hwnd = CreateWindow(szAppName,  TEXT("Analog/*模拟*/ Clock"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT, NULL,NULL, hInstance, NULL);
    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}


//设置笛卡尔坐标系,原点在客户区中央
void SetIsotropic(HDC hdc, int cxClient, int cyClient)
{
    SetMapMode(hdc, MM_ISOTROPIC);
    SetWindowExtEx(hdc, 1000, 1000, NULL);
    SetViewportExtEx(hdc, cxClient / 2, -cyClient / 2, NULL);
    SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
}

//点(x,y)顺时针旋转a角度后,新坐标为(x*cosa+y*sina,y*cona-x*sina)
//可用极坐标求


//将Num个点都顺时针旋转iAngle角度
void RotatePoint(POINT pt[], int iNum, int iAngle)//rotate旋转,循环
{
    int i;
    POINT ptTemp;
    for (i = 0; i < iNum; i++)
    {
        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;
    }
}

//画时钟的60个圆,其中整点的圆直径大些
void DrawClock(HDC hdc)
{
    int iAngle;
    POINT pt[3];
    for (iAngle = 0; iAngle < 360; iAngle += 6)//360/6=12*5
        //每次角度+6,这样就将所有的圆都画出来了
    { 
        pt[0].x = 0;
        pt[0].y = 900;
        //12:00的坐标

        RotatePoint(pt, 1, iAngle);//

        pt[2].x = pt[2].y = iAngle % 5 ? 33 : 100;//保存圆的直径

        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,//时针
        0, -200, 50, 0, 0, 800, -50, 0, 0, -200,//分针
        0, 0, 0, 0, 0, 0, 0, 0, 0, 800//秒针
    };
    //此时三个指针的坐标都是12::00时的


    int i, iAngle[3];
    POINT ptTemp[3][5];

    iAngle[0] = (pst->wHour * 30) % 360 + pst->wMinute / 2;//每经过一小时,时针转动 (时数*6*5),但是并非只是每经过
    //一小时时针才转动,当分针转动时(经过12分钟),时针转动2度(即每经过2分钟,时针转动1度),所以还要加上当前的分时/2

    iAngle[1] = pst->wMinute * 6;//每经过一分钟,分针转动 (分数*6) 度

    iAngle[2] = pst->wSecond * 6;//每经过一秒,秒针转动 (秒数*6) 度

    memcpy(ptTemp,pt, sizeof(pt));

    //时针只有当时或分改变才旋转所有的,否则只用旋转秒针
    for (i = fChange ? 0 : 2; i < 3; i++)
    {
        RotatePoint(ptTemp[i], 5, iAngle[i]);

        Polyline(hdc, ptTemp[i], 5);
    }
}

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

    switch (uMsg)
    {
    case WM_CREATE:
        SetTimer(hwnd, ID_TIMER, 1000,NULL);//每1000毫秒即1秒
        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_CLOSE:
        KillTimer(hwnd, ID_TIMER);
        PostQuitMessage(0);
        //DestroyWindow(hwnd);
        return 0;
  }


        return DefWindowProc(hwnd, uMsg, wParam, lParam);

}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值