好玩的Windows編程之"本地時間"(3) BigBen

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


        }
};

 

最新版的圖



相關文章
相關標籤/搜索