8,计时器应用实例
2015-07-26 10:07
405 查看
示例一:模拟时钟
画钟盘:
SetMapMode(hdc,MM_ISTROPIC) 设置各向同性,才能忽略逻辑单位的不同,画出均匀的表盘。
实现指针的转动:
每隔一秒重绘指针,有必要时也重绘时钟和分针
模拟时钟逻辑:
设置绘图环境-->先绘制钟盘-->获取当前时间,据此绘制当前指针--->每隔一秒获取当前时间并与前一秒比较,再次绘制指针
#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);
每隔一秒重绘指针,有必要时也重绘时钟和分针
模拟时钟逻辑:
设置绘图环境-->先绘制钟盘-->获取当前时间,据此绘制当前指针--->每隔一秒获取当前时间并与前一秒比较,再次绘制指针
相关文章推荐