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