好玩的Windows编程之"本地时间"(3) BigBen

______________________________________

最近又有新的想法了,编一个有指针的钟,名字就叫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);


 




好玩的Windows编程之"本地时间"(3) BigBen_第1张图片

 

好玩的Windows编程之"本地时间"(3) BigBen_第2张图片
同样的方法,我们可以得出分针,时针的公式,同样也容易算出刻度的坐标

 

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时的截图



好玩的Windows编程之"本地时间"(3) BigBen_第3张图片



好玩的Windows编程之"本地时间"(3) BigBen_第4张图片




这就是雏形,不过还有几点问题,数字电子表上,小时数是在分钟从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


  

 半成品

好玩的Windows编程之"本地时间"(3) BigBen_第5张图片
然后有了罗马数字,并剪除了多余的正方形边框


好玩的Windows编程之"本地时间"(3) BigBen_第6张图片



最后用上汉字,完工


好玩的Windows编程之"本地时间"(3) BigBen_第7张图片

 

 

//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

好玩的Windows编程之"本地时间"(3) BigBen_第8张图片

 

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


        }
};

 

最新版的图

好玩的Windows编程之"本地时间"(3) BigBen_第9张图片

好玩的Windows编程之"本地时间"(3) BigBen_第10张图片

 

你可能感兴趣的:(编程,windows,C语言,sdk,gdi)