/*--------------------------------------
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) ;
}
windows程序设计 之 「CLOCK」范例分析笔记
最新推荐文章于 2020-09-01 12:40:24 发布