用easyx画电子钟_一个小小的模拟时钟

本文介绍如何使用EasyX库在Windows上创建一个模拟时钟程序,利用WS_EX_LAYERED属性实现窗口透明效果,结合PS图形制作时钟元素。程序能够通过鼠标操作改变窗口位置和大小,并实时显示当前时间。
摘要由CSDN通过智能技术生成

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

这是第一次分享,求支持,嘻嘻。

看到了@江虾麻 的程序,之前用VC没有编译出来,现在用VS试过之后,真的非常喜欢窗口的WS_EX_LAYERED的属性,能做出许多很有趣的效果,所以今天做了个模拟时钟。

背景是桌面,时钟元素是PS的一些矢量图形。

在自己电脑上Release版本的CPU占用率大约为0.5%。

可以使用鼠标拖拽窗口(但是不是很灵敏),中键开启缩放开关,以便使用滚轮缩放时钟,双击可以退出程序,并且保存当前窗口位置。

话不多说,Show you the code.

//2018-5-12

//that boy

//#include "Button.h"

//#include "ExtensionForEasyX.h"

#include

#include

#include

const double PI = 3.1415926;

const tm& GetClockHandAngle(double &, double &, double &);

int GetClockHandAngle(const tm&,double &, double &, double &);

int DrawClock(const double &, const double &, const double &, bool ForceRecalculate = false);

int DrawClock(int x, int y, const double &, const double &, const double &, bool ForceRecalculate = false);

inline void putimage(int, int, IMAGE&, DWORD dwRop = SRCCOPY);

int ReadWinData(long&, long&, int&);

int SetWinData(long&, long&, int&);

IMAGE ClockDial;

IMAGE HandHour;

IMAGE HandMin;

IMAGE HandSec;

IMAGE NotHandHour;

IMAGE NotHandMin;

IMAGE NotHandSec;

int ClockSize = 300;

const COLORREF BackGroundColor = RGB(1, 1, 1);

const char SetFileName[] = "D:/Program Files/AnalogClock.dat";

bool operator !=(const tm&tm1, const tm&tm2);

bool LoadClockImage();

int APIENTRY WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

double AngleHour = 0, AngleMin = 0, AngleSec = 0;

MOUSEMSG Msg = { NULL };

POINT ScrPos = { 0,0 };

POINT LastPos = { 0,0 };

POINT CurrPos = { 0,0 };

const tm&CurrentTime = GetClockHandAngle(AngleHour, AngleMin, AngleSec);

tm LastTime = { NULL };

bool IsSetSize = false;

bool FreshScreen = false;

bool ResizeScreen = false;

if (ReadWinData(ScrPos.x,ScrPos.y,ClockSize)<3) {//读取数据

ClockSize = 300;

ScrPos.x = (GetSystemMetrics(SM_CXSCREEN) - ClockSize) / 2;

ScrPos.y = (GetSystemMetrics(SM_CYSCREEN) - ClockSize) / 2;

SetWinData(ScrPos.x, ScrPos.y, ClockSize);

}

LoadClockImage();//读取图像

HWND hwnd = initgraph(ClockSize, ClockSize);

SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE)&(~(WS_CAPTION | WS_SYSMENU | WS_SIZEBOX)));

SetWindowLong(hwnd, GWL_EXSTYLE, (GetWindowLong(hwnd, GWL_EXSTYLE)&(~(WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME))) | WS_EX_LAYERED| WS_EX_TOOLWINDOW);

SetWindowPos(hwnd, HWND_TOPMOST, ScrPos.x, ScrPos.y, getwidth(), getheight(), SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_DRAWFRAME);

//设置透明色

SetLayeredWindowAttributes(hwnd, BackGroundColor, 0, LWA_COLORKEY);

setbkcolor(BackGroundColor);

BeginBatchDraw();

FlushMouseMsgBuffer();

while (1)

{

if (MouseHit())

{

GetCursorPos(&CurrPos);

while (MouseHit())

{

Msg = GetMouseMsg();

if (Msg.uMsg == WM_LBUTTONDBLCLK)

{

SetWinData(ScrPos.x, ScrPos.y, ClockSize);

EndBatchDraw();

closegraph();

return 0;

}

else if (Msg.uMsg == WM_LBUTTONDOWN)

{

GetCursorPos(&LastPos);

CurrPos = LastPos;

}

else if (Msg.mkLButton)

{

ScrPos.x += CurrPos.x - LastPos.x;

ScrPos.y += CurrPos.y - LastPos.y;

FreshScreen = true;

GetCursorPos(&LastPos);

}

else if (Msg.uMsg == WM_MBUTTONDOWN)//打开开关

{

IsSetSize = !IsSetSize;

}

else if (IsSetSize&&Msg.wheel != 0)//设置大小

{

ClockSize += Msg.wheel / 40;

ScrPos.x -= Msg.wheel / 80;

ScrPos.y -= Msg.wheel / 80;

ResizeScreen = true;

}

}

if (ResizeScreen)//重设窗口大小

{

Resize(NULL, ClockSize, ClockSize);//设置窗口大小

LoadClockImage();//重新读取图片

SetWindowPos(hwnd, HWND_TOPMOST, ScrPos.x, ScrPos.y, getwidth(), getheight(), SWP_SHOWWINDOW);

GetClockHandAngle(AngleHour, AngleMin, AngleSec);//获得当前指针角度

DrawClock(AngleHour, AngleMin, AngleSec, true);//强制重新生成所有旋转图像

ResizeScreen = false;

}

if (FreshScreen) {

SetWindowPos(hwnd, HWND_TOPMOST, ScrPos.x, ScrPos.y, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE);

FreshScreen = false;

}

}

GetClockHandAngle(AngleHour, AngleMin, AngleSec);

if (LastTime != CurrentTime) {//时间变化才会重绘

DrawClock(AngleHour, AngleMin, AngleSec);

LastTime = CurrentTime;

}

FlushBatchDraw();

Sleep(2);

}

//不会执行到

EndBatchDraw();

closegraph();

return 0;

}

int GetClockHandAngle(const tm&t, double &AngleHour, double &AngleMin, double &AngleSec)

{

static double PI_6 = PI / 6;

static double PI_30 = PI / 30;

AngleHour = (t.tm_hour % 12 + t.tm_min / 60.0)*PI_6;

AngleMin = (t.tm_min + t.tm_sec / 60.0)*PI_30;

AngleSec = (t.tm_sec)*PI_30;

return 0;

}

const tm& GetClockHandAngle(double &AngleHour, double &AngleMin, double &AngleSec)

{

static double PI_6 = PI / 6;

static double PI_30 = PI / 30;

static tm t;

static time_t tick;

if (tick == time(NULL))

return t;

tick = time(NULL);

localtime_s(&t,&tick);

AngleHour = (t.tm_hour % 12 + t.tm_min / 60.0)*PI_6;

AngleMin = (t.tm_min + t.tm_sec / 60.0)*PI_30;

AngleSec = (t.tm_sec)*PI_30;

return t;

}

int DrawClock(const double &AngleHour, const double &AngleMin, const double &AngleSec,bool ForceRecalculate)

{

return DrawClock(getwidth() / 2, getheight() / 2, AngleHour, AngleMin, AngleSec, ForceRecalculate);

}

int DrawClock(int x, int y, const double &AngleHour, const double &AngleMin, const double &AngleSec,bool ForceRecalculate)

{

static IMAGE handHour;

static IMAGE handMin;

static IMAGE handSec;

static IMAGE NhandHour;

static IMAGE NhandMin;

static IMAGE NhandSec;

static double Ah = 0.0, Am = 0.0, As = 0.0;

//保存所有方向指针图像太占用内存,所以实时旋转生成。

if (ForceRecalculate || Ah != AngleHour)

{

rotateimage(&handHour, &HandHour, -AngleHour, BLACK);

rotateimage(&NhandHour, &NotHandHour, -AngleHour, BLACK);

Ah = AngleHour;

}

if (ForceRecalculate || Am != AngleMin)

{

rotateimage(&handMin, &HandMin, -AngleMin, BLACK);

rotateimage(&NhandMin, &NotHandMin, -AngleMin, BLACK);

Am = AngleMin;

}

if (ForceRecalculate || As != AngleSec)

{

rotateimage(&handSec, &HandSec, -AngleSec, BLACK);

rotateimage(&NhandSec, &NotHandSec, -AngleSec, BLACK);

As = AngleSec;

}

putimage(x, y, ClockDial);

putimage(x, y, NhandHour, 0X00220326);

putimage(x, y, handHour, 0X00EE0086);

putimage(x, y, NhandMin, 0X00220326);

putimage(x, y, handMin, 0X00EE0086);

putimage(x, y, NhandSec, 0X00220326);

putimage(x, y, handSec, 0X00EE0086);

return 0;

}

inline void putimage(int x, int y, IMAGE&img, DWORD dwRop)

{

putimage(x - img.getwidth() / 2, y - img.getheight() / 2, &img, dwRop);

}

int ReadWinData(long&x, long&y, int&size)

{

FILE*fp;

fopen_s(&fp, SetFileName, "rb");

if (fp == NULL)

return -1;

int returnint = fread(&x, sizeof(x), 1, fp) + fread(&y, sizeof(x), 1, fp) + fread(&size, sizeof(x), 1, fp);

fclose(fp);

return returnint;

}

int SetWinData(long&x, long&y, int&size)

{

FILE*fp;

fopen_s(&fp, SetFileName, "wb");

if (fp == NULL)

return -1;

int returnint = fwrite(&x, sizeof(x), 1, fp) + fwrite(&y, sizeof(x), 1, fp) + fwrite(&size, sizeof(x), 1, fp);

fclose(fp);

return returnint;

}

bool LoadClockImage()

{

loadimage(&ClockDial, "IMAGE", "CLOCK", ClockSize, ClockSize,true);

loadimage(&HandHour, "IMAGE", "HandHour", ClockSize, ClockSize, true);

loadimage(&HandMin, "IMAGE", "HandMin", ClockSize, ClockSize, true);

loadimage(&HandSec, "IMAGE", "HandSec", ClockSize, ClockSize, true);

loadimage(&NotHandHour, "IMAGE", "~HandHour", ClockSize, ClockSize, true);

loadimage(&NotHandMin, "IMAGE", "~HandMin", ClockSize, ClockSize, true);

loadimage(&NotHandSec, "IMAGE", "~HandSec", ClockSize, ClockSize, true);

return true;

}

bool operator !=(const tm&tm1, const tm&tm2)//判断tm结构体不等,这里只用到了时分秒,所以不对其他成员判断。

{

return tm1.tm_sec != tm2.tm_sec

|| tm1.tm_min != tm2.tm_min

|| tm1.tm_hour != tm2.tm_hour;

}

读取资源文件的地方改成外部文件就好。透明色设为RGB(1,1,1)。

用MFC VC++实现的时钟源代码 // MFCFrame1View.cpp : implementation of the CMFCFrame1View class // #include "stdafx.h" #include "MFCFrame1.h" #include "MFCFrame1Doc.h" #include "MFCFrame1View.h" #include "PointDialog.h" #include "math.h" GLUquadricObj *objCylinder = gluNewQuadric(); #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View IMPLEMENT_DYNCREATE(CMFCFrame1View, CView) BEGIN_MESSAGE_MAP(CMFCFrame1View, CView) //{{AFX_MSG_MAP(CMFCFrame1View) ON_WM_CREATE() ON_WM_DESTROY() ON_WM_SIZE() ON_COMMAND(IDM_ZIXUAN, OnZixuan) ON_WM_TIMER() ON_COMMAND(IDM_ChangDirect, OnChangDirect) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View construction/destruction CMFCFrame1View::CMFCFrame1View() { // TODO: add construction code here this->m_GLPixelIndex = 0; this->m_hGLContext = NULL; Angle1=0.0; Angle2=30.0; Timer=0; x=0.0; z=0.0; juli=40.0; } CMFCFrame1View::~CMFCFrame1View() { } BOOL CMFCFrame1View::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS); return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View drawing ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View printing BOOL CMFCFrame1View::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CMFCFrame1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CMFCFrame1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View diagnostics #ifdef _DEBUG void CMFCFrame1View::AssertValid() const { CView::AssertValid(); } void CMFCFrame1View::Dump(CDumpContext& dc) const { CView::Dump(dc); } CMFCFrame1Doc* CMFCFrame1View::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCFrame1Doc))); return (CMFCFrame1Doc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View message handlers BOOL CMFCFrame1View::SetWindowPixelFormat(HDC hDC) { PIXELFORMATDESCRIPTOR pixelDesc= { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| PFD_DOUBLEBUFFER|PFD_SUPPORT_GDI, PFD_TYPE_RGBA, 24, 0,0,0,0,0,0, 0, 0, 0, 0,0,0,0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0,0,0 }; this->m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc); if(this->m_GLPixelIndex==0) { this->m_GLPixelIndex = 1; if(DescribePixelFormat(hDC,this->m_GLPixelIndex,sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0) { return FALSE; } } if(SetPixelFormat(hDC,this->m_GLPixelIndex,&pixelDesc)==FALSE) { return FALSE; } return TRUE; } int CMFCFrame1View::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here HWND hWnd = this->GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); if(this->SetWindowPixelFormat(hDC)==FALSE) { return 0; } if(this->CreateViewGLContext(hDC)==FALSE) { return 0; } return 0; } BOOL CMFCFrame1View::CreateViewGLContext(HDC hDC) { this->m_hGLContext = wglCreateContext(hDC); if(this->m_hGLContext==NULL) {//创建失败 return FALSE; } if(wglMakeCurrent(hDC,this->m_hGLContext)==FALSE) {//选为当前RC失败 return FALSE; } return TRUE; } void CMFCFrame1View::OnDestroy() { CView::OnDestroy(); // TODO: Add your message handler code here if(wglGetCurrentContext()!=NULL) { wglMakeCurrent(NULL,NULL); } if(this->m_hGLContext!=NULL) { wglDeleteContext(this->m_hGLContext); this->m_hGLContext = NULL; } } void CMFCFrame1View::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // TODO: Add your message handler code here GLsizei width,height; GLdouble aspect; width = cx; height = cy; if(cy==0) { aspect = (GLdouble)width; } else { aspect = (GLdouble)width/(GLdouble)height; } glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0,aspect,5.0,1000.0); } void CMFCFrame1View::OnDraw(CDC* pDC) { CMFCFrame1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPaintDC dc(this); glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0,0.0,10.0,0.0,0.0,0.0,0.0,1.0,0.0); glRotatef(-90.0,1.0,0.0,0.0);/*返回原坐标*/ glTranslatef(-3.0,0.0,0.0); SwapBuffers(dc.m_ps.hdc); glDrawBuffer (GL_BACK); glFlush(); } void CMFCFrame1View::OnZixuan() { // TODO: Add your command handler code here Timer=1; SetTimer(1,100,NULL); } void CMFCFrame1View::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default CPaintDC dc(this); if (Timer==1) { Angle1=Angle1-1; Angle2=Angle2-1; glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW);/**/ glLoadIdentity(); gluLookAt(0.0,20.0,0.000000001,0.0,0.0,0.0,0.0,1.0,0.0); glPushMatrix(); glColor3f(0.7,0.7,0.7); glTranslatef(0.0,0.0,1.1); glRotatef(-90.0,1.0,0.0,0.0); glutSolidCone(5.0,0.0,60.0,60.0); /*底盘*/ glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(3.9,0.99,1.0); /*刻度*/ glRotatef(90.0,0.0,1.0,0.0); gluCylinder(objCylinder, 0.05, 0.05, 0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(-4.7,0.99,1.0); /*刻度*/ glRotatef(90.0,0.0,1.0,0.0); gluCylinder(objCylinder,0.05, 0.05, 0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(0.0,0.99,-2.9); /*刻度*/ glRotatef(180.0,0.0,1.0,0.0); gluCylinder(objCylinder,0.05, 0.05, 0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(0.0,0.99,5.8); /*刻度*/ glRotatef(180.0,0.0,1.0,0.0); gluCylinder(objCylinder,0.05, 0.05,0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,1.0,0.0); glRotatef(45.0,0.0,1.0,0.0); glTranslatef(-0.67,0.99,0.7); /*时针*/ glRotatef(Angle1/129600,0.0,1.0,0.0); gluCylinder(objCylinder, 0.07, 0.02, 2.5, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,0.0); glTranslatef(0.0,0.99,1.0); /*分针*/ glRotatef(Angle2/360,0.0,1.0,0.0); gluCylinder(objCylinder, 0.05, 0.02, 3.5, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.5); glTranslatef(0.0,0.99,1.0); /*秒针*/ glRotatef(Angle1,0.0,1.0,0.0); gluCylinder(objCylinder, 0.07, 0.02, 4.5, 9999, 9); glPopMatrix(); SwapBuffers(dc.m_ps.hdc); glDrawBuffer (GL_BACK); glFlush(); } else if(Timer==2) { glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); if (juli>12.0) { glMatrixMode(GL_MODELVIEW);/*建立了从世界坐标系到观察坐标系的转换矩阵*/ glLoadIdentity(); gluLookAt(0.0,8.0,juli,0.0,0.0,0.0,0.0,1.0,0.0); juli=juli-0.1; glPushMatrix(); glColor3f(0.0,0.0,0.0); glRotatef(-90.0,1.0,0.0,0.0); glutWireCone(40.0,0.0,30.0,30.0); /*高度为0的圆锥*/ glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glLineWidth(4.0); glTranslatef(4.0,1.0,0.0); glutWireOctahedron(); /*八面体*/ glLineWidth(1.0); glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glTranslatef(0.0,1.1,0.0); glRotatef(Angle2,0.0,1.0,0.0); gluCylinder(objCylinder, 1.0, 1.0, 10.0, 9999, 9); /*壶*/ glPopMatrix(); } else if(juli<=12.0) { Angle2=Angle2+0.01; if (Angle2==360.0) Angle2=0.0; glMatrixMode(GL_MODELVIEW);/*建立了从世界坐标系到观察坐标系的转换矩阵*/ glLoadIdentity(); x=12.0*sin(Angle2); z=12.0*cos(Angle2); gluLookAt(x,5.0,z,0.0,0.0,0.0,0.0,1.0,0.0); glPushMatrix(); glColor3f(0.0,0.0,0.0); glRotatef(-90.0,1.0,0.0,0.0); glutWireCone(40.0,0.0,30.0,30.0); /*高度为0的圆锥*/ glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glLineWidth(4.0); glTranslatef(4.0,1.0,0.0); glutWireOctahedron(); /*八面体*/ glLineWidth(1.0); glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glTranslatef(0.0,1.1,0.0); gluCylinder(objCylinder, 1.0, 1.0, 10.0, 9999, 9); /*壶*/ glPopMatrix(); } SwapBuffers(dc.m_ps.hdc); glDrawBuffer (GL_BACK); glFlush(); } CView::OnTimer(nIDEvent); } void CMFCFrame1View::OnChangDirect() { // TODO: Add your command handler code here Timer=2; SetTimer(1,100 ,NULL); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值