/*--------------------------------------
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 发布