使用场景
你可以将这个精心编写的程序编译成可执行文件,并优雅地放置在桌面上,宛如一件匠心独运的小摆件。它不仅能够实时展示日历与精准的时间,还能作为一件别出心裁的装饰品,为你的桌面增添一抹独特的风景。若你渴望在这个程序的基础上融入自己独一无二的创意,那么,一个专属于你的个性化日历日期摆件便应运而生。而若你追求更加细腻精巧的设计,渴望将它雕琢成一个令人赞叹的精美摆件,那么,只需发挥你的想象力与创造力,一个既实用又充满艺术气息的桌面摆件便指日可待。
效果
你也可以创新一下加个你喜欢的背景图,如下图。
源码普通版本
///////////////////////////////////////////////////
// 程序名称:Easyx日历时钟
// 编译环境:Mictosoft Visual Studio 2022, EasyX_20200315(beta)
// 作 者:luoyh <2864292458@qq.com>
// 公 众 号:C语言研究
// 最后修改:2024-10-27
//
SYSTEMTIME t; //定义变量保存当前时间
void Drawtime(); // 实时更新时间
void DrawWeek(); // 绘制星期
void DrawDays(); // 绘制日期
int dayOftheWeekThisYear(int year);
int dayOftheWeekThisYearQueryMonth(int year, int month);
int countdays(int y, int m, int d); // 计算从 0001-1-1 起的天数
int monthdays(int y, int m); // 计算某月的天数
void DralDial(int X, int Y);
void DrawHand(int hour, int minute, int second, int X, int Y);
void digital(int h, int m, int s, int X, int Y);
int main()
{
initgraph(640, 420);
setbkcolor(RGB(196, 199, 191));
cleardevice();
BeginBatchDraw();
while (true)
{
setfillcolor(BLACK);
solidroundrect(40, 30, 600, 330, 50, 50);
GetLocalTime(&t); //获取当前时间
DralDial(190, 180); //画表盘
DrawHand(t.wHour, t.wMinute, t.wSecond, 190, 180); //画表针
//digital(t.wHour, t.wMinute, t.wSecond,190,180); // 显示时间
Drawtime();
DrawWeek();
DrawDays();
setlinecolor(BLACK); // 装饰
line(15, 127, 15, 233);
line(25, 127, 25, 233);
line(610, 85, 610, 120);
line(620, 85, 620, 120);
line(610, 85 + 120, 610, 120 + 120);
line(620, 85 + 120, 620, 120 + 120);
setfillcolor(RGB(43, 38, 36));
for (int i = 0; i < 3; i++)
{
fillroundrect(128 + i * 50, 366, 160 + i * 50, 400, 8, 8);
}
settextcolor(RGB(112, 71, 79));
settextstyle(30, 0, L"楷体");
outtextxy(413, 366, _T("C语言研究"));
FlushBatchDraw();
}
EndBatchDraw();
_getch();
return 0;
}
void Drawtime() // 实时更新时间
{
setbkmode(TRANSPARENT);
settextcolor(RGB(112, 71, 79));
settextstyle(25, 0, L"微软雅黑");
//RECT r = { 348, 50, 580, 70 };
SYSTEMTIME t; //定义变量保存当前时间
wchar_t s2[126];
GetLocalTime(&t);
swprintf_s(s2, 126, L"%d年%d月%d日 %d:%02d:%02d", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
outtextxy(355, 50, s2);
}
void DrawWeek() // 绘制星期
{
settextstyle(25, 0, L"微软雅黑");
settextcolor(WHITE);
TCHAR str[25];
for (int i = 0; i < 7; i++)
{
str[0] = L"SMTWTFS"[i];
str[1] = L""[0];
RECT r = { 348 + 35 * i,90,378 + 35 * i,110 };
if (i == 0 || i == 6)
{
settextcolor(RGB(112, 71, 79));
}
else
{
settextcolor(WHITE);
}
drawtext(str, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
void DrawDays() // 绘制日期
{
GetLocalTime(&t);
int weeks = dayOftheWeekThisYearQueryMonth(t.wYear, t.wMonth); // 获取该月1号是星期几
int WEEKSJ = weeks;
int days = monthdays(t.wYear, t.wMonth); // 获取该月天数
TCHAR str_day[25];
settextcolor(WHITE);
// 设置输出效果为抗锯齿 (VC6 / VC2008 / VC2010 / VC2012)
LOGFONT f;
gettextstyle(&f); // 获取当前字体设置
f.lfHeight = 25; // 设置字体高度为 40
wcscpy_s(f.lfFaceName, _T("微软雅黑")); // 设置字体为“黑体”(高版本 VC 推荐使用 _tcscpy_s 函数)
f.lfQuality = ANTIALIASED_QUALITY; // 设置输出效果为抗锯齿
f.lfWeight = 1000;
settextstyle(&f); // 设置字体样式
int GD = 0;
int KD = 0;
for (int i = 0; i < days; i++)
{
_stprintf_s(str_day, _T("%d"), i + 1);
if ((WEEKSJ + i) % 7 == 0)
{
GD++;
KD = 0;
weeks = 0;
settextcolor(RGB(112, 71, 79));
}
if ((WEEKSJ + i) % 7 == 6)
{
settextcolor(RGB(112, 71, 79));
}
RECT r = { 348 + 35 * (KD + weeks), 110 + 40 * GD, 383 + 35 * (KD + weeks), 150 + 40 * GD };
drawtext(str_day, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
if ((i + 1) == t.wDay) // 如果是今天的日期
{
setfillcolor(RED);
solidrectangle(348 + 35 * (KD + weeks), 110 + 40 * GD, 383 + 35 * (KD + weeks), 150 + 40 * GD);
settextcolor(WHITE);
drawtext(str_day, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
settextcolor(WHITE);
KD++;
}
}
int dayOftheWeekThisYear(int year)
{
int i = ((5 * (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400) % 7) + 1;
return i;
//蔡勒公式,此处是计算这一年的第一天是星期几
}
//查询某年某月的第一天星期几,需要调用上一个函数实现
int dayOftheWeekThisYearQueryMonth(int year, int month)
{
int totalDays = countdays(year, month, 1) - countdays(year, 1, 1);
totalDays = totalDays + dayOftheWeekThisYear(year);
return (totalDays % 7);
//把这个天数和加上之前计算的查询年的第一天的星期几在进行计算,即可求出查询月的第一天是星期几
}
int countdays(int y, int m, int d)
{
if (m < 3) y--, m += 12;
return 365 * y + (y >> 2) - y / 100 + y / 400 + (153 * m - 457) / 5 + d - 306;
}
int monthdays(int y, int m)
{
if (m == 2)
return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) ? 29 : 28;
else
return 31 - (m - 3) % 5 % 2;
}
/*画表盘*/
void DralDial(int X, int Y)
{
setbkmode(TRANSPARENT);
int x1, y1, x2, y2;
setlinecolor(RGB(100, 100, 100));
setlinestyle(PS_SOLID | PS_ENDCAP_SQUARE, 1);
for (int i = 0; i <= 59; i++)
{
// 画60条短线
x1 = (int)(X + (sin(i * PI / 30) * 120));
y1 = (int)(Y - (cos(i * PI / 30) * 120));
x2 = (int)(X + (sin(i * PI / 30) * 130));
y2 = (int)(Y - (cos(i * PI / 30) * 130));
if (i % 5)
{
line(x1, y1, x2, y2);
}
}
settextcolor(WHITE);
//写表盘数字
for (int n = 0; n < 12; n++)
{
wchar_t s[10];
swprintf_s(s, 10, L"%d", 12 - n); // int 类型转换成 char 类型
settextstyle(50, 0, _T("微软雅黑"));
// 定义字符串长和宽,居中
int w, h;
w = textwidth(s);
h = textheight(s);
outtextxy(int(95 * cos(n * 2 * PI / 12 + PI / 2) - w / 2) + X,
-int(95 * sin(n * 2 * PI / 12 + PI / 2) + h / 2) + Y, s);
}
for (int n = 0; n < 12; n++)
{
wchar_t s[10];
swprintf_s(s, 10, L"%02d", (12 - n) * 5); // int 类型转换成 char 类型
settextstyle(20, 0, _T("微软雅黑"));
// 定义字符串长和宽,居中
int w, h;
w = textwidth(s);
h = textheight(s);
outtextxy(int(125 * cos(n * 2 * PI / 12 + PI / 2) - w / 2) + X,
-int(125 * sin(n * 2 * PI / 12 + PI / 2) + h / 2) + Y, s);
}
}
//画指针
void DrawHand(int hour, int minute, int second, int X, int Y)
{
int xhour, yhour, xminute, yminute, xsecond, ysecond; //表心坐标系指针坐标
xhour = (int)(90 * sin(hour * PI / 6 + minute * PI / 360 + second * PI / 1800));
yhour = (int)(90 * cos(hour * PI / 6 + minute * PI / 360 + second * PI / 1800));
xminute = (int)(110 * sin(minute * PI / 30 + second * PI / 1800));
yminute = (int)(110 * cos(minute * PI / 30 + second * PI / 1800));
xsecond = (int)(125 * sin(second * PI / 30));
ysecond = (int)(125 * cos(second * PI / 30));
//画时针
setlinecolor(WHITE);
setlinestyle(PS_SOLID, 5);
line(X + xhour, Y - yhour, X, Y);
setlinestyle(PS_SOLID, 10);
line(X + xhour, Y - yhour, X + xhour / 3, Y - yhour / 3);
//画分针
setlinestyle(PS_SOLID, 5);
line(X + xminute, Y - yminute, X, Y);
setlinestyle(PS_SOLID, 10);
line(X + xminute, Y - yminute, X + xminute / 5, Y - yminute / 5);
//画秒针
setfillcolor(WHITE);
solidcircle(X, Y, 8);
setlinecolor(RGB(190, 151, 118));
setlinestyle(PS_SOLID, 3);
circle(X, Y, 5);
line(X + xsecond, Y - ysecond, X - xsecond / 5, Y + ysecond / 5);
setfillcolor(RGB(35, 0, 0));
solidcircle(X, Y, 3);
}
// 显示数字时钟
void digital(int h, int m, int s, int X, int Y)
{
// 画显示当前时间的三个小矩形
setlinecolor(LIGHTGRAY); // 设置边框颜色为浅灰色
setfillcolor(WHITE); // 设置填充颜色为白色
fillrectangle(X - 40 - 13, Y + 50, X - 40 + 13, Y + 50 + 26);
fillrectangle(X - 13, Y + 50, X + 13, Y + 50 + 26);
fillrectangle(X + 40 - 13, Y + 50, X + 40 + 13, Y + 50 + 26);
// 显示当前时间
settextstyle(24, 0, _T("微软雅黑"));
wchar_t a[10];
int w;
settextcolor(BLACK);
swprintf_s(a, 10, L"%02d", h); w = textwidth(a); outtextxy(X - 40 - w / 2, Y + 50, a);
swprintf_s(a, 10, L"%02d", m); w = textwidth(a); outtextxy(X - w / 2, Y + 50, a);
swprintf_s(a, 10, L"%02d", s); w = textwidth(a); outtextxy(X + 40 - w / 2, Y + 50, a);
}
动态效果
///////////////////////////////////////////////////
// 程序名称:Easyx日历时钟创新版本
// 编译环境:Mictosoft Visual Studio 2022, EasyX_20200315(beta)
// 作 者:luoyh <2864292458@qq.com>
// 公 众 号:C语言研究
// 最后修改:2024-10-27
//
SYSTEMTIME t; //定义变量保存当前时间
void Drawtime(); // 实时更新时间
void DrawWeek(); // 绘制星期
void DrawDays(); // 绘制日期
int dayOftheWeekThisYear(int year);
int dayOftheWeekThisYearQueryMonth(int year, int month);
int countdays(int y, int m, int d); // 计算从 0001-1-1 起的天数
int monthdays(int y, int m); // 计算某月的天数
void DralDial(int X, int Y);
void DrawHand(int hour, int minute, int second, int X, int Y);
void digital(int h, int m, int s, int X, int Y);
bool SetWindowTransparent(HWND hwnd, COLORREF crkcolor, BYTE bAlpha, DWORD dwFlags);
void SetWindowsForm(HWND hWnd);
int main()
{
initgraph(640, 420);
setbkcolor(RGB(196, 199, 191));
cleardevice();
HWND hWnd = GetHWnd(); // 获取窗口句柄
SetWindowsForm(hWnd); // 设置为窗口为圆形并透明
ExMessage m; // 定义鼠标消息
BeginBatchDraw();
while (true)
{
while (peekmessage(&m, EX_MOUSE)) // 如果获取到了消息就执行
{
switch (m.message)
{
case WM_LBUTTONDOWN:
// 如果左键按下,欺骗 windows 点在了标题栏上
PostMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(m.x, m.y));
break;
}
}
setfillcolor(BLACK);
solidroundrect(40, 30, 600, 330, 50, 50);
GetLocalTime(&t); //获取当前时间
DralDial(190, 180); //画表盘
DrawHand(t.wHour, t.wMinute, t.wSecond, 190, 180); //画表针
//digital(t.wHour, t.wMinute, t.wSecond,190,180); // 显示时间
Drawtime();
DrawWeek();
DrawDays();
setlinecolor(BLACK); // 装饰
line(15, 127, 15, 233);
line(25, 127, 25, 233);
line(610, 85, 610, 120);
line(620, 85, 620, 120);
line(610, 85 + 120, 610, 120 + 120);
line(620, 85 + 120, 620, 120 + 120);
setfillcolor(RGB(43, 38, 36));
for (int i = 0; i < 3; i++)
{
fillroundrect(128 + i * 50, 366, 160 + i * 50, 400, 8, 8);
}
settextcolor(RGB(112, 71, 79));
settextstyle(30, 0, L"楷体");
outtextxy(413, 366, _T("C语言研究"));
FlushBatchDraw();
}
EndBatchDraw();
_getch();
return 0;
}
void Drawtime() // 实时更新时间
{
setbkmode(TRANSPARENT);
settextcolor(RGB(112, 71, 79));
settextstyle(25, 0, L"微软雅黑");
//RECT r = { 348, 50, 580, 70 };
SYSTEMTIME t; //定义变量保存当前时间
wchar_t s2[126];
GetLocalTime(&t);
swprintf_s(s2, 126, L"%d年%d月%d日 %d:%02d:%02d", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
outtextxy(355, 50, s2);
}
void DrawWeek() // 绘制星期
{
settextstyle(25, 0, L"微软雅黑");
settextcolor(WHITE);
TCHAR str[25];
for (int i = 0; i < 7; i++)
{
str[0] = L"SMTWTFS"[i];
str[1] = L""[0];
RECT r = { 348 + 35 * i,90,378 + 35 * i,110 };
if (i == 0 || i == 6)
{
settextcolor(RGB(112, 71, 79));
}
else
{
settextcolor(WHITE);
}
drawtext(str, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
void DrawDays() // 绘制日期
{
GetLocalTime(&t);
int weeks = dayOftheWeekThisYearQueryMonth(t.wYear, t.wMonth); // 获取该月1号是星期几
int WEEKSJ = weeks;
int days = monthdays(t.wYear, t.wMonth); // 获取该月天数
TCHAR str_day[25];
settextcolor(WHITE);
// 设置输出效果为抗锯齿 (VC6 / VC2008 / VC2010 / VC2012)
LOGFONT f;
gettextstyle(&f); // 获取当前字体设置
f.lfHeight = 25; // 设置字体高度为 40
wcscpy_s(f.lfFaceName, _T("微软雅黑")); // 设置字体为“黑体”(高版本 VC 推荐使用 _tcscpy_s 函数)
f.lfQuality = ANTIALIASED_QUALITY; // 设置输出效果为抗锯齿
f.lfWeight = 1000;
settextstyle(&f); // 设置字体样式
int GD = 0;
int KD = 0;
for (int i = 0; i < days; i++)
{
_stprintf_s(str_day, _T("%d"), i + 1);
if ((WEEKSJ + i) % 7 == 0)
{
GD++;
KD = 0;
weeks = 0;
settextcolor(RGB(112, 71, 79));
}
if ((WEEKSJ + i) % 7 == 6)
{
settextcolor(RGB(112, 71, 79));
}
RECT r = { 348 + 35 * (KD + weeks), 110 + 40 * GD, 383 + 35 * (KD + weeks), 150 + 40 * GD };
drawtext(str_day, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
if ((i + 1) == t.wDay) // 如果是今天的日期
{
setfillcolor(RED);
solidrectangle(348 + 35 * (KD + weeks), 110 + 40 * GD, 383 + 35 * (KD + weeks), 150 + 40 * GD);
settextcolor(WHITE);
drawtext(str_day, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
settextcolor(WHITE);
KD++;
}
}
int dayOftheWeekThisYear(int year)
{
int i = ((5 * (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400) % 7) + 1;
return i;
//蔡勒公式,此处是计算这一年的第一天是星期几
}
//查询某年某月的第一天星期几,需要调用上一个函数实现
int dayOftheWeekThisYearQueryMonth(int year, int month)
{
int totalDays = countdays(year, month, 1) - countdays(year, 1, 1);
totalDays = totalDays + dayOftheWeekThisYear(year);
return (totalDays % 7);
//把这个天数和加上之前计算的查询年的第一天的星期几在进行计算,即可求出查询月的第一天是星期几
}
int countdays(int y, int m, int d)
{
if (m < 3) y--, m += 12;
return 365 * y + (y >> 2) - y / 100 + y / 400 + (153 * m - 457) / 5 + d - 306;
}
int monthdays(int y, int m)
{
if (m == 2)
return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) ? 29 : 28;
else
return 31 - (m - 3) % 5 % 2;
}
/*画表盘*/
void DralDial(int X, int Y)
{
setbkmode(TRANSPARENT);
int x1, y1, x2, y2;
setlinecolor(RGB(100, 100, 100));
setlinestyle(PS_SOLID | PS_ENDCAP_SQUARE, 1);
for (int i = 0; i <= 59; i++)
{
// 画60条短线
x1 = (int)(X + (sin(i * PI / 30) * 120));
y1 = (int)(Y - (cos(i * PI / 30) * 120));
x2 = (int)(X + (sin(i * PI / 30) * 130));
y2 = (int)(Y - (cos(i * PI / 30) * 130));
if (i % 5)
{
line(x1, y1, x2, y2);
}
}
settextcolor(WHITE);
//写表盘数字
for (int n = 0; n < 12; n++)
{
wchar_t s[10];
swprintf_s(s, 10, L"%d", 12 - n); // int 类型转换成 char 类型
settextstyle(50, 0, _T("微软雅黑"));
// 定义字符串长和宽,居中
int w, h;
w = textwidth(s);
h = textheight(s);
outtextxy(int(95 * cos(n * 2 * PI / 12 + PI / 2) - w / 2) + X,
-int(95 * sin(n * 2 * PI / 12 + PI / 2) + h / 2) + Y, s);
}
for (int n = 0; n < 12; n++)
{
wchar_t s[10];
swprintf_s(s, 10, L"%02d", (12 - n) * 5); // int 类型转换成 char 类型
settextstyle(20, 0, _T("微软雅黑"));
// 定义字符串长和宽,居中
int w, h;
w = textwidth(s);
h = textheight(s);
outtextxy(int(125 * cos(n * 2 * PI / 12 + PI / 2) - w / 2) + X,
-int(125 * sin(n * 2 * PI / 12 + PI / 2) + h / 2) + Y, s);
}
}
//画指针
void DrawHand(int hour, int minute, int second, int X, int Y)
{
int xhour, yhour, xminute, yminute, xsecond, ysecond; //表心坐标系指针坐标
xhour = (int)(90 * sin(hour * PI / 6 + minute * PI / 360 + second * PI / 1800));
yhour = (int)(90 * cos(hour * PI / 6 + minute * PI / 360 + second * PI / 1800));
xminute = (int)(110 * sin(minute * PI / 30 + second * PI / 1800));
yminute = (int)(110 * cos(minute * PI / 30 + second * PI / 1800));
xsecond = (int)(125 * sin(second * PI / 30));
ysecond = (int)(125 * cos(second * PI / 30));
//画时针
setlinecolor(WHITE);
setlinestyle(PS_SOLID, 5);
line(X + xhour, Y - yhour, X, Y);
setlinestyle(PS_SOLID, 10);
line(X + xhour, Y - yhour, X + xhour / 3, Y - yhour / 3);
//画分针
setlinestyle(PS_SOLID, 5);
line(X + xminute, Y - yminute, X, Y);
setlinestyle(PS_SOLID, 10);
line(X + xminute, Y - yminute, X + xminute / 5, Y - yminute / 5);
//画秒针
setfillcolor(WHITE);
solidcircle(X, Y, 8);
setlinecolor(RGB(190, 151, 118));
setlinestyle(PS_SOLID, 3);
circle(X, Y, 5);
line(X + xsecond, Y - ysecond, X - xsecond / 5, Y + ysecond / 5);
setfillcolor(RGB(35, 0, 0));
solidcircle(X, Y, 3);
}
// 显示数字时钟
void digital(int h, int m, int s, int X, int Y)
{
// 画显示当前时间的三个小矩形
setlinecolor(LIGHTGRAY); // 设置边框颜色为浅灰色
setfillcolor(WHITE); // 设置填充颜色为白色
fillrectangle(X - 40 - 13, Y + 50, X - 40 + 13, Y + 50 + 26);
fillrectangle(X - 13, Y + 50, X + 13, Y + 50 + 26);
fillrectangle(X + 40 - 13, Y + 50, X + 40 + 13, Y + 50 + 26);
// 显示当前时间
settextstyle(24, 0, _T("微软雅黑"));
wchar_t a[10];
int w;
settextcolor(BLACK);
swprintf_s(a, 10, L"%02d", h); w = textwidth(a); outtextxy(X - 40 - w / 2, Y + 50, a);
swprintf_s(a, 10, L"%02d", m); w = textwidth(a); outtextxy(X - w / 2, Y + 50, a);
swprintf_s(a, 10, L"%02d", s); w = textwidth(a); outtextxy(X + 40 - w / 2, Y + 50, a);
}
bool SetWindowTransparent(HWND hwnd, COLORREF crkcolor, BYTE bAlpha, DWORD dwFlags)
{
HINSTANCE hm = GetModuleHandle(_T("USER32.DLL"));
if (hm)
{
FARPROC fun = GetProcAddress(hm, "SetLayeredWindowAttributes");
bool (WINAPI * SetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD) = (bool (WINAPI*) (HWND, COLORREF, BYTE, DWORD))fun;
if (SetLayeredWindowAttributes)
{
LONG ret = GetWindowLong(hwnd, GWL_EXSTYLE);
ret |= WS_EX_LAYERED;
SetWindowLong(hwnd, GWL_EXSTYLE, ret);
SetLayeredWindowAttributes(hwnd, crkcolor, bAlpha, dwFlags);
}
FreeLibrary(hm);
return true;
}
else
{
return false;
}
}
void SetWindowsForm(HWND hWnd)
{
setbkcolor(RGB(196, 199, 191));
cleardevice();
// 获取窗口边框宽高
RECT rcClient, rcWind;
GetClientRect(hWnd, &rcClient);
GetWindowRect(hWnd, &rcWind);
int cx = ((rcWind.right - rcWind.left) - rcClient.right) / 2;
int cy = ((rcWind.bottom - rcWind.top + GetSystemMetrics(SM_CYCAPTION)) - rcClient.bottom) / 2;
HRGN rgn = CreateRectRgn(0 + cx, 0 + cy, 640 + cx, 420 + cy);
SetWindowRgn(hWnd, rgn, true);
SetWindowTransparent(hWnd, RGB(196, 199, 191), 100, 0x1);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
加强版本动态效果