______________________________________
最近又有新的想法了,编一个有指针的钟,名字就叫BigBen.(下载页面)
原理很简单:首先要取得本地时间,然后把时间转化成钟的指针画上去,最后再把边沿剪切掉,就是一个桌面指针时钟了.
开工了!!!
_______________________________________
原理
时针走时角度是圆的十二等分,走一刻度的角度 alpha=360/12(角度)=PI/180*360/12(弧度)
秒和分针走时角度是圆的六十等分,走一刻度角度alpha=360/60(角度)=PI/180*360/60(弧度)
圆心的坐标pt0(m,n)和半径r是已知的,我们可以算出秒针的轨迹坐标pt(x,y)=(r*cos(sec*alpha)+m,r*sin(sec*alpha)+n)
把秒数代入公式得到pt(x,y)=(r*cos(sec*PI/180*360/60)+m,r*sin(sec*PI/180*360/60)+n),然后从圆心pt(m,n)画线到pt(x,y)就是秒针,或者分针了,慢着!什么地方错了.
由于时钟是以90度计为0秒,不是0度,所以要减去90度(即PI/2弧度),所以上面的公式修正为pt(x,y)=(r*cos(sec*PI/180*360/60-PI/2)+m,r*sin(sec*PI/180*360/60-PI/2)+n)=(r*cos(sec*PI/30-PI/2)+m,r*sin(sec*PI/30-PI/2)+n),这样还是有点错误,在C语言下,整数代入计算可能会因为求整,舍去小数而产生误差.于是再把公式改成这样子pt(x,y)=(r*cos(sec*PI/30.0-PI/2.0)+m,r*sin(sec*PI/30.0-PI/2.0)+n)
SYSTEMTIME current_time; POINT pt0; POINT pt; GetLocalTime(&ct); pt.x=r*cos(ct.wSecond*PI/30.0-PI/2.0)+pt0.x;pt.y=r*sin(ct.wSecond*PI/30.0-PI/2.0)+pt0.yMoveToEx(hdc,pt0.x,pt0.y,NULL); LineTo(hdc,pt.x,pt.y);
同样的方法,我们可以得出分针,时针的公式,同样也容易算出刻度的坐标
m_alpha_min=m_time.wMinute*PI/30.0-PI/2; m_alpha_hour=m_time.wHour*PI/6.0-PI/2.0; m_ptmin.x=m_rmin*cos(m_alpha_min)+m_pt0.x; m_ptmin.y=m_rmin*sin(m_alpha_min)+m_pt0.y; m_pthour.x=m_rhour*cos(m_alpha_hour)+m_pt0.x; m_pthour.y=m_rhour*sin(m_alpha_hour)+m_pt0.y);
下图是出现BUG时的截图
这就是雏形,不过还有几点问题,数字电子表上,小时数是在分钟从59变00时,才加1,跳变的,如果直接画在表上,会产生什么呢,分针到了59秒时,时针突然从上一个刻度上跳变!!!有白天见鬼的感觉,而且容易让人产生错觉,所以时针计算公式还要改进.也就是分针行进过程,时针要缓缓前行,然后自然而然地随着分针到了59,00时,小时也到了下一个刻度.想想...想想--走60分钟,时针行进一刻度,也就是PI/180*(360/12)弧度,那走一分钟就是 +PI/180*(360/12)*((m_time.wMinute/60));这是就在原来时针走的角度上加上这个微小的角度.
m_alpha_hour=m_time.wHour*PI/6.0-PI/2.0+PI/360.0*m_time.wMinute;
有了这个想法,我想我们也可以改动秒针让它也,缓缓移动.一般情况下秒针一秒跳一次,或许你也见过平滑流动行走的秒针吧,那就要请出微秒
m_alpha_sec=(m_time.wSecond+( m_bsmooth ? m_time.wMilliseconds/1000.0 :0.0 ) )*PI/30.0-PI/2;//平滑秒针跳走second+m_time.wMilliseconds/1000.0
半成品
//BigBen.h //程序名:BigBen //作者wisepragma //主页:http://blog.csdn.net/wisepragma #pragma once #include <cmath>//#define EDGE_LENGTH 600 //#define FONT_WIDTH 14 //#define FONT_HIGHT 14//#define EDGE_LENGTH 400 //#define FONT_WIDTH 14 //#define FONT_HIGHT 14#define EDGE_LENGTH 250 #define FONT_WIDTH 5 #define FONT_HIGHT 5//时钟的外观设定 #define COLOR_HOUR (RGB(224,63,196)) #define COLOR_MINUTE (RGB(255,0,0)) #define COLOR_SECOND (RGB(0,255,255)) #define COLOR_BACK (RGB(0,0,0))TCHAR *clktxt[]={TEXT("天"),TEXT("道"),TEXT("酬"),TEXT("勤"),TEXT("静"),TEXT("以"),TEXT("修"),TEXT("身"),TEXT("检"),TEXT("以"),TEXT("养"),TEXT("德")}; //TCHAR *clktxt[12]={TEXT("XII"),TEXT("I"),TEXT("II"),TEXT("III"),TEXT("IV"),TEXT("V"),TEXT("VI"),TEXT("VII"),TEXT("VIII"),TEXT("IX"),TEXT("X"),TEXT("XI")}; ////TCHAR *clktxt[]={TEXT("待"),TEXT("我"),TEXT("君"),TEXT("临"),TEXT("天"),TEXT("下"),TEXT("许"),TEXT("你"),TEXT("四"),TEXT("海"),TEXT("为"),TEXT("家")}; //// //TCHAR *clktxt[]={TEXT("历"),TEXT("史"),TEXT("尘"),TEXT("封"),TEXT("了"),TEXT("锁"), TEXT("在"),TEXT("岁"),TEXT("月"),TEXT("的"),TEXT("橱"),TEXT("窗")}; // // TCHAR *clktxt[]={TEXT("12"),TEXT("1"),TEXT("2"),TEXT("3"),TEXT("4"),TEXT("5"),TEXT("6"),TEXT("7"),TEXT("8"),TEXT("9"),TEXT("10"),TEXT("11")}; class XPEN { private: HPEN m_hpen,m_hpenold; HDC m_hdc; public: XPEN(HDC hdc,COLORREF clr,int width=1) { m_hdc=hdc; m_hpen=CreatePen(PS_SOLID,width,clr); m_hpenold=static_cast<HPEN>(SelectObject(m_hdc,m_hpen)); } void select(COLORREF clr,int width=1) { SelectObject(m_hdc,m_hpenold); DeleteObject(m_hpen); m_hpen=CreatePen(PS_SOLID,width,clr); m_hpenold=(HPEN)SelectObject(m_hdc,m_hpen); } ~XPEN() { SelectObject(m_hdc,m_hpenold); DeleteObject(m_hpen); } }; class XBRUSH { private: HBRUSH m_hbrush,m_hbrold; HDC m_hdc; public: XBRUSH(HDC hdc,int br) { m_hdc=hdc; m_hbrush=static_cast<HBRUSH>(GetStockObject(br));//会自动填充白色画刷而覆盖其他色彩 m_hbrold=static_cast<HBRUSH>(SelectObject(m_hdc,m_hbrush)); } XBRUSH(HDC hdc,COLORREF clr) { m_hdc=hdc; m_hbrush=static_cast<HBRUSH>(CreateSolidBrush(clr));//会自动填充白色画刷而覆盖其他色彩 m_hbrold=static_cast<HBRUSH>(SelectObject(m_hdc,m_hbrush)); } void select(COLORREF clr) { SelectObject(m_hdc,m_hbrold); DeleteObject(m_hbrush); m_hbrush=CreateSolidBrush(clr); m_hbrold=static_cast<HBRUSH>(SelectObject(m_hdc,m_hbrold)); } HBRUSH get() { return m_hbrush; } ~XBRUSH() { SelectObject(m_hdc,m_hbrold); DeleteObject(m_hbrush); } }; class XBigBen { private: COLORREF m_clrHour,m_clrMinute,m_clrSecond,m_clrBack; SYSTEMTIME m_time; unsigned int m_r,m_rsec_tail,m_rhour,m_rmin,m_rsec; POINT m_pt0,m_ptedge,m_ptsec,m_ptmin,m_pthour,m_ptsec_tail; RECT m_rc; double m_alpha_sec,m_alpha_min,m_alpha_hour; const double PI; bool m_bsmooth; TCHAR m_clktxt[12][15]; public: bool m_bAdjustWindow; XBigBen(int x,int y,int r, COLORREF clrh=RGB(224,63,196), COLORREF clrm=RGB(255,0,0), COLORREF clrs=RGB(0,255,255), COLORREF clrbk=RGB(0,0,0)) :PI(3.1415) { m_clrHour=clrh; m_clrMinute=clrm; m_clrSecond=clrs; m_clrBack=clrbk; m_r=r; m_pt0.x=x; m_pt0.y=y; m_rc.left=m_pt0.x-m_r; m_rc.top=m_pt0.y-m_r; m_rc.right=m_pt0.x+m_r; m_rc.bottom=m_pt0.y+m_r; m_rsec_tail=m_r/4; m_rsec=m_r*85/100; m_rmin=m_r*80/100; m_rhour=m_r*60/100; m_bsmooth=true; m_bAdjustWindow=true; //TCHAR *str[12]={TEXT("XII"),TEXT("I"),TEXT("II"),TEXT("III"),TEXT("IV"),TEXT("V"),TEXT("VI"),TEXT("VII"),TEXT("VIII"),TEXT("IX"),TEXT("X"),TEXT("XI")}; //setclktext(str); } void setclktext(TCHAR *ptxt[12]) { for(int i=0;i<12;i++) { lstrcpy(m_clktxt[i],ptxt[i]); } } void gettime() { GetLocalTime(&m_time); //秒针,分针都是圆的六十等分(360/60),走一秒为n*6度,由于C函数用的参数变弧度,所以n*6再乘以转化率PSECOND/180=n*6*PI/180=n*PI/30=n*3.1415/30===n*360.0/60.0*3.1415/180,由于时钟是以90度计为0秒,不是0度,所以要减去90度(即PI/2) //时针是圆的十二等分(360/12)===360.0/12*3.1415/180,分针行进过程中,时针缓缓地步进到下一个刻度 m_alpha_sec=(m_time.wSecond+( m_bsmooth ? m_time.wMilliseconds/1000.0 :0.0 ) )*PI/30.0-PI/2;//平滑秒针跳走second+m_time.wMilliseconds/1000.0 m_alpha_min=m_time.wMinute*PI/30.0-PI/2; m_alpha_hour=m_time.wHour*PI/6.0-PI/2.0+PI/360.0*m_time.wMinute;//分针行进过程中,时针缓缓地步进到下一个刻度,而不像数字表那样瞬间跳变,一定要用浮点数代入计算,否则将被求整而产生错误m_alpha_hour=m_time.wHour*PI/6-PI/2+PI/180*(360/12)*((m_time.wMinute/60)); m_ptsec.x=static_cast<long>(m_rsec*cos(m_alpha_sec)+m_pt0.x); m_ptsec.y=static_cast<long>(m_rsec*sin(m_alpha_sec)+m_pt0.y); m_ptsec_tail.x=static_cast<long>(m_rsec_tail*cos(m_alpha_sec+PI)+m_pt0.x); m_ptsec_tail.y=static_cast<long>(m_rsec_tail*sin(m_alpha_sec+PI)+m_pt0.y);//当拷贝粘贴时错误也一并拷贝 m_ptedge.x=static_cast<long>(m_r*cos(m_alpha_sec)+m_pt0.x); m_ptedge.y=static_cast<long>(m_r*sin(m_alpha_sec)+m_pt0.y); m_ptmin.x=static_cast<long>(m_rmin*cos(m_alpha_min)+m_pt0.x); m_ptmin.y=static_cast<long>(m_rmin*sin(m_alpha_min)+m_pt0.y); m_pthour.x=static_cast<long>(m_rhour*cos(m_alpha_hour)+m_pt0.x); m_pthour.y=static_cast<long>(m_rhour*sin(m_alpha_hour)+m_pt0.y); } void drawcircle(HDC hdc,POINT pt,int r,COLORREF clr,int width=1)//pt为圆心,半径为r,以clr色彩画圆 { XPEN hpen(hdc,clr,width); XBRUSH hbr(hdc,HOLLOW_BRUSH); //若不设定为(HOLLOW_BRUSH);会自动填充白色画刷而覆盖其他色彩 RECT rc0; rc0.left=pt.x-r; rc0.top=pt.y-r; rc0.right=pt.x+r; rc0.bottom=pt.y+r; Ellipse(hdc,rc0.left,rc0.top,rc0.right,rc0.bottom );//指针的中心圆点 } void show(HWND hwnd,HDC hdc) { RECT rcwnd; //client rect GetClientRect(hwnd,&rcwnd); HDC hmem=CreateCompatibleDC(hdc);//使用缓冲BitBlt方式避免闪烁 HBITMAP hbmp=CreateCompatibleBitmap(hdc,rcwnd.right-rcwnd.left,rcwnd.bottom-rcwnd.top);//RIGHT-LEFT NO LEFT-RIGHT,一出错全是白的 SelectObject(hmem,hbmp); XBRUSH brBack(hmem,m_clrBack); FillRect(hmem,&rcwnd,brBack.get());//背景着色 gettime();//取得时间,并计算各时钟指针的坐标 drawface(hmem); //表盘刻度 和文字 drawhour(hmem); //画时针 drawminute(hmem);//画分针 drawsecond(hmem); //画秒针 drawcircle(hmem,m_pt0,4,RGB(0,0,255),2); BitBlt(hdc,0,0,rcwnd.right-rcwnd.left,rcwnd.bottom-rcwnd.top,hmem,0,0,SRCCOPY );// SRCCOPY刷新//SRCAND重叠 DeleteObject(hbmp); DeleteDC(hmem); int t=6; HRGN hrgn= CreateEllipticRgn (m_rc.left-t+3,m_rc.top-t+2,m_rc.right+t,m_rc.bottom+t); SetWindowRgn(hwnd,hrgn,TRUE);//把窗口切成圆的 } void line(HDC hdc,POINT pt1,POINT pt2) { MoveToEx(hdc,pt1.x,pt1.y,NULL); LineTo(hdc,pt2.x,pt2.y); } void drawhour(HDC hdc) { XPEN hpen(hdc,m_clrHour,4); line(hdc,m_pt0,m_pthour); } void drawminute(HDC hdc) { XPEN hpen(hdc,m_clrMinute,3); line(hdc,m_pt0,m_ptmin); } void drawsecond(HDC hdc) { XPEN hpen(hdc,m_clrSecond,2); SetPixel(hdc,m_ptedge.x,m_ptedge.y,RGB(255,0,0)); line(hdc,m_pt0,m_ptsec); //hpen.select(RGB(146,250,43),2);//秒针的尾巴色彩 line(hdc,m_pt0,m_ptsec_tail); } void drawface(HDC hdc) { for(int i=0;i<60;i++)//绘制分钟,秒钟的刻度 { double beta=i*PI/30.0-PI/2.0; POINT ptedge;//圆框的点的位置 ptedge.x=static_cast<long>(m_r*cos(beta)+m_pt0.x); ptedge.y=static_cast<long>(m_r*sin(beta)+m_pt0.y); POINT ptit;//时刻度的点的位置 ptit.x=static_cast<long>((m_rsec*1.1)*cos(beta)+m_pt0.x); ptit.y=static_cast<long>((m_rsec*1.1)*sin(beta)+m_pt0.y); XPEN hpen(hdc,RGB(159,34,241),2); line(hdc,ptit,ptedge); if(i%5==0) { XPEN hpen(hdc,RGB(51,140,183),3);//绘制时钟刻度的位置 ptit.x=static_cast<long>((m_rsec+1.0)*cos(beta)+m_pt0.x); ptit.y=static_cast<long>((m_rsec+1.0)*sin(beta)+m_pt0.y); POINT ptit_num;//时间的数值的位置 ptit_num.x=static_cast<long>((m_rsec-15.0)*cos(beta)+m_pt0.x);//数值为微调位置 ptit_num.y=static_cast<long>((m_rsec-9.0)*sin(beta)+m_pt0.y); line(hdc,ptit,ptedge); TEXTMETRIC tm; LOGFONT lf={0}; GetTextMetrics(hdc,&tm); lstrcpy(lf.lfFaceName,TEXT("Lucida")); lf.lfHeight= tm.tmHeight+FONT_HIGHT; lf.lfWidth=tm.tmAveCharWidth+FONT_WIDTH ; HFONT hfont=CreateFontIndirect(&lf); HGDIOBJ hdcOld=SelectObject(hdc,hfont); SIZE sz; GetTextExtentPoint32(hdc,m_clktxt[i/5],lstrlen(m_clktxt[i/5]),&sz); SetBkMode(hdc,TRANSPARENT);//使文字背景透明 SetTextColor(hdc,RGB(190,177,27)); TextOut(hdc,ptit_num.x-sz.cx/2,ptit_num.y-sz.cy/2,m_clktxt[i/5],lstrlen(m_clktxt[i/5])); SelectObject(hdc,hdcOld);//还原否则字体会不断变大 DeleteObject(hfont); } } XBRUSH hbr(hdc,HOLLOW_BRUSH); drawcircle(hdc,m_pt0,m_r,RGB(191,138,28),3); } };
// BigBen.cpp //程序名:BigBen //作者wisepragma //主页:http://blog.csdn.net/wisepragma #include "stdafx.h" #include "BigBen.h" #include <cmath> #pragma comment(lib,"user32.lib") #pragma comment(lib,"gdi32.lib") XBigBen BigBen(EDGE_LENGTH/2,EDGE_LENGTH/2,(EDGE_LENGTH-10)/2,COLOR_HOUR,COLOR_MINUTE,COLOR_SECOND, COLOR_BACK ); //________________________________________________________________ TCHAR szTitle[ ]=TEXT("BigBen"); // 标题栏文本 TCHAR szWindowClass[ ]=TEXT("BigCls"); // 主窗口类名 ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); MSG msg; MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_QUESTION)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = static_cast<HBRUSH>(0);//(WHITE_BRUSH);(COLOR_WINDOW+1);//有色的背景某此情下会造成闪烁 wcex.lpszMenuName =NULL;// MAKEINTRESOURCE(IDC_BigBen); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_QUESTION)); return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd =CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW, szWindowClass,szTitle,WS_POPUPWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,EDGE_LENGTH,EDGE_LENGTH, NULL,NULL,hInstance,NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_LBUTTONDOWN: RECT rcWnd; GetWindowRect(hWnd,&rcWnd); SendMessage(hWnd,WM_NCLBUTTONDOWN,HTCAPTION,lParam); GetWindowRect(hWnd,&rcWnd); if(rcWnd.top<0) MoveWindow(hWnd,rcWnd.left,0,EDGE_LENGTH,EDGE_LENGTH,TRUE);//WIN7下窗口超出顶端会变形,所以要调整 break; case WM_KEYDOWN: if(wParam==VK_ESCAPE)PostQuitMessage(0); break; case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); BigBen.show(hWnd,hdc); EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_CREATE: BigBen.setclktext(clktxt); SetTimer(hWnd,0,100,NULL); if(BigBen.m_bAdjustWindow) { RECT rectDesktop; SystemParametersInfo(SPI_GETWORKAREA,0,&rectDesktop,0); MoveWindow( hWnd, GetSystemMetrics(SM_CXFULLSCREEN)-EDGE_LENGTH,//微调 rectDesktop.bottom-EDGE_LENGTH,//rectDesktop.bottom是系统状态栏最高处的纵坐标 EDGE_LENGTH, EDGE_LENGTH, TRUE); BigBen.m_bAdjustWindow=false; } break; case WM_TIMER: InvalidateRect(hWnd,NULL,TRUE); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
最新版本加入这张背景图片IMAGE.BMP
//resource.h的内容 #define IDI_IMAGE 180
//BigBen.rc的内容 //编译方式:RC /v BigBen.rc //显示:Writing BITMAP:180, lang:0x804, size 313240. #include "resource.h" IDI_IMAGE BITMAP "image.bmp"
//BigBen.h //更新版本:1.1 //程序名:BigBen //作者wisepragma //主页:http://blog.csdn.net/wisepragma #pragma once #include "resource.h" #include <cmath> //#define EDGE_LENGTH 600 //#define FONT_WIDTH 14 //#define FONT_HIGHT 14 // //#define EDGE_LENGTH 400 //#define FONT_WIDTH 11 //#define FONT_HIGHT 11 #define EDGE_LENGTH 250 #define FONT_WIDTH 5 #define FONT_HIGHT 5 //#define EDGE_LENGTH 150 //#define FONT_WIDTH 1 //#define FONT_HIGHT 1 //时钟的外观设定 #define COLOR_HOUR (RGB(155,30,255))//2014.3.24 add (RGB(224,63,196)) #define COLOR_MINUTE (RGB(0,49,255))//(RGB(255,0,0)) #define COLOR_SECOND (RGB(0,255,255)) #define COLOR_BACK (RGB(0,0,0)) #define COLOR_TEXT (RGB(255,0,0))//(0)//RGB(162,120,9)RGB(0,200,128));//字体色彩RGB(190,177,27)RGB(142,36,162)RGB(94,36,126) TCHAR *clktxt[]={TEXT("天"),TEXT("道"),TEXT("酬"),TEXT("勤"),TEXT("静"),TEXT("以"),TEXT("修"),TEXT("身"),TEXT("检"),TEXT("以"),TEXT("养"),TEXT("德")}; //TCHAR *clktxt[12]={TEXT("XII"),TEXT("I"),TEXT("II"),TEXT("III"),TEXT("IV"),TEXT("V"),TEXT("VI"),TEXT("VII"),TEXT("VIII"),TEXT("IX"),TEXT("X"),TEXT("XI")}; ////TCHAR *clktxt[]={TEXT("待"),TEXT("我"),TEXT("君"),TEXT("临"),TEXT("天"),TEXT("下"),TEXT("许"),TEXT("你"),TEXT("四"),TEXT("海"),TEXT("为"),TEXT("家")}; //// //TCHAR *clktxt[]={TEXT("历"),TEXT("史"),TEXT("尘"),TEXT("封"),TEXT("了"),TEXT("锁"), TEXT("在"),TEXT("岁"),TEXT("月"),TEXT("的"),TEXT("橱"),TEXT("窗")}; // // TCHAR *clktxt[]={TEXT("12"),TEXT("1"),TEXT("2"),TEXT("3"),TEXT("4"),TEXT("5"),TEXT("6"),TEXT("7"),TEXT("8"),TEXT("9"),TEXT("10"),TEXT("11")}; class XPEN { private: HPEN m_hpen,m_hpenold; HDC m_hdc; public: XPEN(HDC hdc,COLORREF clr,int width=1) { m_hdc=hdc; m_hpen=CreatePen(PS_SOLID,width,clr); m_hpenold=static_cast<HPEN>(SelectObject(m_hdc,m_hpen)); } void select(COLORREF clr,int width=1) { SelectObject(m_hdc,m_hpenold); DeleteObject(m_hpen); m_hpen=CreatePen(PS_SOLID,width,clr); m_hpenold=(HPEN)SelectObject(m_hdc,m_hpen); } ~XPEN() { SelectObject(m_hdc,m_hpenold); DeleteObject(m_hpen); } }; class XBRUSH { private: HBRUSH m_hbrush,m_hbrold; HDC m_hdc; public: XBRUSH(HDC hdc,int br) { m_hdc=hdc; m_hbrush=static_cast<HBRUSH>(GetStockObject(br));//会自动填充白色画刷而覆盖其他色彩 m_hbrold=static_cast<HBRUSH>(SelectObject(m_hdc,m_hbrush)); } XBRUSH(HDC hdc,COLORREF clr) { m_hdc=hdc; m_hbrush=static_cast<HBRUSH>(CreateSolidBrush(clr));//会自动填充白色画刷而覆盖其他色彩 m_hbrold=static_cast<HBRUSH>(SelectObject(m_hdc,m_hbrush)); } void select(COLORREF clr) { SelectObject(m_hdc,m_hbrold); DeleteObject(m_hbrush); m_hbrush=CreateSolidBrush(clr); m_hbrold=static_cast<HBRUSH>(SelectObject(m_hdc,m_hbrold)); } HBRUSH get() { return m_hbrush; } ~XBRUSH() { SelectObject(m_hdc,m_hbrold); DeleteObject(m_hbrush); } }; class XBigBen { private: COLORREF m_clrHour,m_clrMinute,m_clrSecond,m_clrBack; SYSTEMTIME m_time; unsigned int m_r,m_rsec_tail,m_rhour,m_rmin,m_rsec; POINT m_pt0,m_ptedge,m_ptsec,m_ptmin,m_pthour,m_ptsec_tail; RECT m_rc; double m_alpha_sec,m_alpha_min,m_alpha_hour; const double PI; bool m_bsmooth; TCHAR m_clktxt[12][15]; public: bool m_bAdjustWindow; XBigBen(int x,int y,int r, COLORREF clrh=RGB(224,63,196), COLORREF clrm=RGB(255,0,0), COLORREF clrs=RGB(0,255,255), COLORREF clrbk=RGB(0,0,0)) :PI(3.1415) { m_clrHour=clrh; m_clrMinute=clrm; m_clrSecond=clrs; m_clrBack=clrbk; m_r=r; m_pt0.x=x; m_pt0.y=y; m_rc.left=m_pt0.x-m_r; m_rc.top=m_pt0.y-m_r; m_rc.right=m_pt0.x+m_r; m_rc.bottom=m_pt0.y+m_r; m_rsec_tail=m_r/4; m_rsec=m_r*85/100; m_rmin=m_r*80/100; m_rhour=m_r*60/100; m_bsmooth=true; m_bAdjustWindow=true; //TCHAR *str[12]={TEXT("XII"),TEXT("I"),TEXT("II"),TEXT("III"),TEXT("IV"),TEXT("V"),TEXT("VI"),TEXT("VII"),TEXT("VIII"),TEXT("IX"),TEXT("X"),TEXT("XI")}; //setclktext(str); } void setclktext(TCHAR *ptxt[12]) { for(int i=0;i<12;i++) { lstrcpy(m_clktxt[i],ptxt[i]); } } void gettime() { GetLocalTime(&m_time); //秒针,分针都是圆的六十等分(360/60),走一秒为n*6度,由于C函数用的参数变弧度,所以n*6再乘以转化率PSECOND/180=n*6*PI/180=n*PI/30=n*3.1415/30===n*360.0/60.0*3.1415/180,由于时钟是以90度计为0秒,不是0度,所以要减去90度(即PI/2) //时针是圆的十二等分(360/12)===360.0/12*3.1415/180,分针行进过程中,时针缓缓地步进到下一个刻度 m_alpha_sec=(m_time.wSecond+( m_bsmooth ? m_time.wMilliseconds/1000.0 :0.0 ) )*PI/30.0-PI/2;//平滑秒针跳走second+m_time.wMilliseconds/1000.0 m_alpha_min=m_time.wMinute*PI/30.0-PI/2; m_alpha_hour=m_time.wHour*PI/6.0-PI/2.0+PI/360.0*m_time.wMinute;//分针行进过程中,时针缓缓地步进到下一个刻度,而不像数字表那样瞬间跳变,一定要用浮点数代入计算,否则将被求整而产生错误m_alpha_hour=m_time.wHour*PI/6-PI/2+PI/180*(360/12)*((m_time.wMinute/60)); m_ptsec.x=static_cast<long>(m_rsec*cos(m_alpha_sec)+m_pt0.x); m_ptsec.y=static_cast<long>(m_rsec*sin(m_alpha_sec)+m_pt0.y); m_ptsec_tail.x=static_cast<long>(m_rsec_tail*cos(m_alpha_sec+PI)+m_pt0.x); m_ptsec_tail.y=static_cast<long>(m_rsec_tail*sin(m_alpha_sec+PI)+m_pt0.y);//当拷贝粘贴时错误也一并拷贝 m_ptedge.x=static_cast<long>(m_r*cos(m_alpha_sec)+m_pt0.x); m_ptedge.y=static_cast<long>(m_r*sin(m_alpha_sec)+m_pt0.y); m_ptmin.x=static_cast<long>(m_rmin*cos(m_alpha_min)+m_pt0.x); m_ptmin.y=static_cast<long>(m_rmin*sin(m_alpha_min)+m_pt0.y); m_pthour.x=static_cast<long>(m_rhour*cos(m_alpha_hour)+m_pt0.x); m_pthour.y=static_cast<long>(m_rhour*sin(m_alpha_hour)+m_pt0.y); } void drawcircle(HDC hdc,POINT pt,int r,COLORREF clr,int width=1)//pt为圆心,半径为r,以clr色彩画圆 { XPEN hpen(hdc,clr,width); XBRUSH hbr(hdc,HOLLOW_BRUSH); //若不设定为(HOLLOW_BRUSH);会自动填充白色画刷而覆盖其他色彩 RECT rc0; rc0.left=pt.x-r; rc0.top=pt.y-r; rc0.right=pt.x+r; rc0.bottom=pt.y+r; Ellipse(hdc,rc0.left,rc0.top,rc0.right,rc0.bottom );//指针的中心圆点 } void show(HWND hwnd,HDC hdc) { RECT rcwnd; //client rect GetClientRect(hwnd,&rcwnd); HDC hmem=CreateCompatibleDC(hdc);//使用缓冲BitBlt方式避免闪烁 HBITMAP hbmp=CreateCompatibleBitmap(hdc,rcwnd.right-rcwnd.left,rcwnd.bottom-rcwnd.top);//RIGHT-LEFT NO LEFT-RIGHT,一出错全是白的 SelectObject(hmem,hbmp); XBRUSH brBack(hmem,m_clrBack); FillRect(hmem,&rcwnd,brBack.get());//背景着色 HANDLE hbitmp=LoadImage( GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_IMAGE), IMAGE_BITMAP , EDGE_LENGTH , EDGE_LENGTH , LR_LOADTRANSPARENT ); SelectObject(hmem,hbitmp); gettime();//取得时间,并计算各时钟指针的坐标 drawface(hmem); //表盘刻度 和文字 drawhour(hmem); //画时针 drawminute(hmem);//画分针 drawsecond(hmem); //画秒针 drawcircle(hmem,m_pt0,4,RGB(0,0,255),2); BitBlt(hdc,0,0,rcwnd.right-rcwnd.left,rcwnd.bottom-rcwnd.top,hmem,0,0,SRCCOPY );// SRCCOPY刷新//SRCAND重叠 DeleteObject(hbitmp); DeleteObject(hbmp); DeleteDC(hmem); int t=6; HRGN hrgn= CreateEllipticRgn (m_rc.left-t+4,m_rc.top-t+4,m_rc.right+t-2,m_rc.bottom+t-2);//change2014.3.24 SetWindowRgn(hwnd,hrgn,TRUE);//把窗口切成圆的 } void line(HDC hdc,POINT pt1,POINT pt2) { MoveToEx(hdc,pt1.x,pt1.y,NULL); LineTo(hdc,pt2.x,pt2.y); } void drawhour(HDC hdc) { XPEN hpen(hdc,m_clrHour,4); line(hdc,m_pt0,m_pthour); } void drawminute(HDC hdc) { XPEN hpen(hdc,m_clrMinute,3); line(hdc,m_pt0,m_ptmin); } void drawsecond(HDC hdc) { XPEN hpen(hdc,m_clrSecond,2); SetPixel(hdc,m_ptedge.x,m_ptedge.y,RGB(255,0,0)); line(hdc,m_pt0,m_ptsec); //hpen.select(RGB(146,250,43),2);//秒针的尾巴色彩 line(hdc,m_pt0,m_ptsec_tail); } void drawface(HDC hdc) { for(int i=0;i<60;i++)//绘制分钟,秒钟的刻度 { double beta=i*PI/30.0-PI/2.0; POINT ptedge;//圆框的点的位置 ptedge.x=static_cast<long>(m_r*cos(beta)+m_pt0.x); ptedge.y=static_cast<long>(m_r*sin(beta)+m_pt0.y); POINT ptit;//时刻度的点的位置 ptit.x=static_cast<long>((m_rsec*1.1)*cos(beta)+m_pt0.x); ptit.y=static_cast<long>((m_rsec*1.1)*sin(beta)+m_pt0.y); XPEN hpen(hdc,RGB(159,34,241),2); line(hdc,ptit,ptedge); if(i%5==0) { XPEN hpen(hdc,RGB(51,140,183),3);//绘制时钟刻度的位置 ptit.x=static_cast<long>((m_rsec+1.0)*cos(beta)+m_pt0.x); ptit.y=static_cast<long>((m_rsec+1.0)*sin(beta)+m_pt0.y); POINT ptit_num;//时间的数值的位置 ptit_num.x=static_cast<long>((m_rsec-10.0)*cos(beta)+m_pt0.x);//数值为微调位置change2014.3.24 ptit_num.y=static_cast<long>((m_rsec-9.0)*sin(beta)+m_pt0.y); line(hdc,ptit,ptedge); TEXTMETRIC tm; LOGFONT lf={0}; GetTextMetrics(hdc,&tm); lstrcpy(lf.lfFaceName,TEXT("Lucida")); lf.lfHeight= tm.tmHeight+FONT_HIGHT; lf.lfWidth=tm.tmAveCharWidth+FONT_WIDTH ; HFONT hfont=CreateFontIndirect(&lf); HGDIOBJ hdcOld=SelectObject(hdc,hfont); SIZE sz; GetTextExtentPoint32(hdc,m_clktxt[i/5],lstrlen(m_clktxt[i/5]),&sz); SetBkMode(hdc,TRANSPARENT);//使文字背景透明 SetTextColor(hdc,COLOR_TEXT);//字体色彩RGB(190,177,27)RGB(142,36,162)RGB(94,36,126) TextOut(hdc,ptit_num.x-sz.cx/2,ptit_num.y-sz.cy/2,m_clktxt[i/5],lstrlen(m_clktxt[i/5])); SelectObject(hdc,hdcOld);//还原否则字体会不断变大 DeleteObject(hfont); } } XBRUSH hbr(hdc,HOLLOW_BRUSH); drawcircle(hdc,m_pt0,m_r,RGB(191,138,28),3); } };
最新版的图