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         = LoadIcon (NULL, IDI_APPLICATION) ;
     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,横轴-2000~2000

	SetWindowExtEx(hdc,1000,1000,NULL);                         
	SetViewportExtEx(hdc,cxClient/2,-cyClient/2,NULL);   
	
	//将客户区中心设为(0,0)

	SetViewportOrgEx(hdc,cxClient/2,cyClient/2,NULL);           
}


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;     //12个位置的直径为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,800};
	int		i,iAngle[3];
	POINT	ptTemp[3][5];

	iAngle[0]=(pst->wHour*30)%360 +pst->wMinute/2;     //60/2=30等于时钟的一个单位
	iAngle[1]=pst->wMinute*6;
	iAngle[2]=pst->wSecond*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 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);                       //hwnd:当前窗口句柄
		SetIsotropic(hdc,cxClient,cyClient);   //hdc:  设备环境句柄,初始化环境

		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);
}




画钟盘:

SetMapMode(hdc,MM_ISTROPIC)  设置各向同性,才能忽略逻辑单位的不同,画出均匀的表盘。


实现指针的转动:

SelectObject(hdc,GetStockObject(WHITE_PEN));  //抹掉之前的
DrawHands(hdc,&stPrevious,fChange);   

SelectObject(hdc,GetStockObject(BLACK_PEN));  //重绘现在的
DrawHands(hdc,&st,TRUE);  

每隔一秒重绘指针,有必要时也重绘时钟和分针



模拟时钟逻辑:


设置绘图环境-->先绘制钟盘-->获取当前时间,据此绘制当前指针--->每隔一秒获取当前时间并与前一秒比较,再次绘制指针



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值