模拟时钟:
/*---------------------------------------------------------
s046.c---a daily practice
046.c WIN32 API 每日一练
第46个例子:模拟时钟
RotatePoint 函数顺时针旋转
SetIsotropic 函数---设置视窗参数
DrwaClock 函数---画时钟
DrawHands函数---画指针
2023 7.8
-----------------------------------------------------------*/
#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("this 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); //映射模式等比例缩放
SetWindowExtEx(hdc, 1000, 1000, NULL); //指定的值设置窗口设备上下文的水平和垂直范围
SetViewportExtEx(hdc, cxClient / 2, -cyClient / 2, NULL); //使用指定的值设置为视口设倍
SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL); //设置视口原点
}
//顺时针旋转 公式: x=x*cos(a)+y*sin(a);y=y*cos(a)-x*sin(a);
void RotatePoint(POINT pt[], int iNum, int iAngle)
{
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;
}
}
//画时钟的刻度
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);
pt[2].x = pt[2].y = iAngle % 5 ? 33 : 100;//圆的大小(直径)
//Ellipse左上角的矩形坐标点
pt[0].x -= pt[2].x / 2;
pt[0].y -= pt[2].y / 2;
//Ellipse右下角的矩形坐标点
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 fChang)
{
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//秒针
};
int i, iAngle[3];
POINT ptTemp[3][5];
iAngle[0] = (pst->wHour * 30) % 360 + pst->wMinute / 2;//时针每小时30度
iAngle[1] = pst->wMinute * 6;//每分钟,分钟走6度。
iAngle[2] = pst->wSecond * 6;//每分,秒针走6度。
memcpy(ptTemp, pt, sizeof(pt));
//判断是否只画秒针0-1-2或者2
for (i = fChang ? 0 : 2; i < 3; i++)
{
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);
}