______________________________________html
最近又有新的想法了,編一個有指針的鐘,名字就叫BigBen.(下載頁面)
原理很簡單:首先要取得本地時間,而後把時間轉化成鐘的指針畫上去,最後再把邊沿剪切掉,就是一個桌面指針時鐘了.函數
開工了!!!字體
_______________________________________
原理ui
時針走時角度是圓的十二等分,走一刻度的角度 alpha=360/12(角度)=PI/180*360/12(弧度)
秒和分針走時角度是圓的六十等分,走一刻度角度alpha=360/60(角度)=PI/180*360/60(弧度)spa
圓心的座標pt0(m,n)和半徑r是已知的,咱們能夠算出秒針的軌跡座標pt(x,y)=(r*cos(sec*alpha)+m,r*sin(sec*alpha)+n).net
把秒數代入公式獲得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)code
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);
一樣的方法,咱們能夠得出分針,時針的公式,一樣也容易算出刻度的座標htm
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時的截圖
blog
這就是雛形,不過還有幾點問題,數字電子錶上,小時數是在分鐘從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); } };
最新版的圖