有智能手表的人都知道,前段时间的“太空人表盘”非常火热。被称为6块钱的快乐。但其实动手做这样一款太空人表盘并不难。我们也可以自己动手来制作一款太空人表盘。经过我的一番研究,总算制作成功了。今天就来分享给大家。
准备- Visual Studio 2019
- EasyX Graphics Library :Visual C++ 的免费绘图库
- #ifndef _HUAWEI_H_
- #define _HUAWEI_H_
- #include<graphics.h>
- void SetWindowNewStyle(int w, int h)
- {
- // 去掉标题
- SetWindowLong(GetHWnd(), GWL_STYLE, GetWindowLong(GetHWnd(), GWL_STYLE) & ~WS_CAPTION);
- // 初始化界面为圆形
- SetWindowRgn(GetHWnd(), CreateEllipticRgn(0, 0, w, h), true);
- }
- //png透明贴图
- void drawImg(IMAGE* pimg, int x, int y)
- {
- // 变量初始化
- DWORD* dst = GetImageBuffer();
- DWORD* src = GetImageBuffer(pimg);
- int dst_width = ::getwidth(); //窗口宽高
- int dst_height = ::getheight();
- int _w = pimg->getwidth();
- int _h = pimg->getheight();
- // 计算贴图的实际长宽
- int iwidth = (x + _w > dst_width) ? dst_width - x : _w; // 处理超出右边界
- int iheight = (y + _h > dst_height) ? dst_height - y : _h; // 处理超出下边界
- if (x < 0) { src += -x; iwidth -= -x; x = 0; } // 处理超出左边界
- if (y < 0) { src += (_w * -y); iheight -= -y; y = 0; } // 处理超出上边界
- // 修正贴图起始位置
- dst += (dst_width * y + x);
- // 实现透明贴图
- for (int iy = 0; iy < iheight; iy++)
- {
- for (int ix = 0; ix < iwidth; ix++)
- {
- byte a = (byte)(src[ix] >> 24);//计算透明通道的值[0,256) 0为完全透明 255为完全不透明
- if (a > 100)
- {
- dst[ix] = src[ix];
- }
- }
- //换到下一行
- dst += dst_width;
- src += _w;
- }
- }
- //去掉窗口标题以后,能够点击移动窗口
- void mouseEvent()
- {
- //求鼠标相对于当前窗口左上角的坐标(即鼠标距离窗口左上的的宽度和高度)
- static POINT WndPtSize;
- static bool isMove = false;
- if (MouseHit())
- {
- MOUSEMSG msg = GetMouseMsg();
- if (msg.uMsg == WM_LBUTTONDOWN) //左键按下
- {
- //获取窗口相对与屏幕左上角的 左上角坐标,和右下角坐标
- RECT wndRect;
- GetWindowRect(GetHWnd(), &wndRect);
- //获取鼠标光标相对于屏幕的坐标
- POINT curPos;
- GetCursorPos(&curPos);
- //求鼠标相对于当前窗口左上角的坐标
- WndPtSize.x = curPos.x - wndRect.left;
- WndPtSize.y = curPos.y - wndRect.top;
- isMove = true;
- }
- else if (msg.uMsg == WM_LBUTTONUP)//左键弹起
- {
- isMove = false;
- }
- else if (msg.uMsg == WM_MOUSEMOVE)//鼠标移动
- {
- if (isMove)
- {
- POINT CursorPos;
- GetCursorPos(&CursorPos);
- /*把窗口移动到屏幕的x,y的位置
- * @hwnd:窗口句柄
- * @hwndInsertAfter:窗口的z顺序 HWND_TOPMOST {在前面, 位于任何顶部窗口的前面}
- * @X,Y: 窗口左上角的新位置(相对于屏幕)
- * @cx,xy: 窗口大小
- * @uFlags:SWP_NOSIZE {忽略 cx、cy, 保持大小}
- */
- SetWindowPos(GetHWnd(), HWND_TOPMOST, CursorPos.x - WndPtSize.x, CursorPos.y - WndPtSize.y, 0, 0, SWP_NOSIZE);
- //CursorPos.x - WndPtSize.x //获取当前窗口左上角相对于屏幕的坐标
- //CursorPos.y - WndPtSize.y
- //printf("%d %d\n", CursorPos.x - WndPtSize.x, CursorPos.y - WndPtSize.y);
- }
- }
- else if (msg.uMsg == WM_RBUTTONDOWN)//右键按下
- {
- exit(0);
- }
- }
- }
- #endif // !_TOOLS_H_
- #include <stdio.h>
- #include <time.h>
- #include "huawei.h"
- #include <mmsystem.h>
- #pragma comment(lib,"winmm.lib")
- #pragma warning(disable:4996)
- /*
- 1,文本字体设置
- 2,图片动画效果
- 3,绘制表盘
- */
- #define WIN_SIZE 500
- #define WIN_HALF (WIN_SIZE/2) //窗口的一半
- IMAGE spaceMan[59];
- IMAGE other[6];
- const char *week[7] = { "日","一","二","三","四","五","六" };
- void setTextStyle(int height, int width, const char *faceName)
- {
- LOGFONT f = { 0 };
- f.lfHeight = height;
- f.lfWidth = width;
- f.lfQuality = ANTIALIASED_QUALITY;
- strcpy(f.lfFaceName, faceName);
- settextstyle(&f);
- }
- void loadImg()
- {
- mciSendString("D:\\VS\\作品\\智能表盘\\images/风儿吹.mp3", NULL, 0, NULL);
- mciSendString("D:\\VS\\作品\\智能表盘\\images/风儿吹.mp3 repeat", NULL, 0, NULL);
- char fileName[50] = { 0 };
- for (int i = 0; i < 30; i++)
- {
- sprintf_s(fileName, "./images/guoguoxiaoshidi (%d).jpeg", i + 1);
- loadimage(spaceMan + i, fileName, 140, 130);
- }
- loadimage(&other[0], "./images/xinlv.jpg", 60, 60);//心率
- loadimage(&other[1], "./images/sun.jpg", 40, 40);//太阳
- loadimage(&other[2], "./images/shoes.jpg", 40, 40);//鞋子
- loadimage(&other[3], "./images/shang.jpg", 30, 30);//上箭头
- loadimage(&other[4], "./images/xia.jpg", 30, 30);//下箭头
- loadimage(&other[5], "./images/rocket.jpg", 40, 40);//火箭
- }
- //太空人旋转动画
- void animation()
- {
- static int index = 0; //[0~59)
- putimage(175, 210, spaceMan + index);
- static DWORD t1;
- DWORD t2 = clock();//获取程序运行到调用该函数经过的毫秒
- if (t2 - t1 > 20)
- {
- index = (index + 1) % 30;
- t1 = t2;
- }
- }
- void gameDraw()
- {
- setbkcolor(RGB(255, 0, 0));
- cleardevice();
- //绘制表盘
- setlinecolor(RGB(0, 0, 0));//设置边框颜色
- setlinestyle(PS_SOLID, 30);
- setfillcolor(RGB(255, 255, 255));//设置圆的填充白色
- fillellipse(0, 0, WIN_SIZE, WIN_SIZE);//绘制一个圆
- //绘制线条
- setlinestyle(PS_SOLID, 4);
- setlinecolor(BLACK);
- //最上面竖线
- line(WIN_HALF - 30, 20, WIN_HALF - 30, 130);
- //横线x2
- line(WIN_HALF - 195, WIN_HALF - 120, WIN_HALF + 195, WIN_HALF - 120);
- line(WIN_HALF - 195, WIN_HALF + 120, WIN_HALF + 195, WIN_HALF + 120);
- //下面线条x3
- line(WIN_HALF + 80, WIN_HALF + 120, WIN_HALF + 80, WIN_HALF + 175);
- line(WIN_HALF + 80, WIN_HALF + 175, WIN_HALF - 60, WIN_HALF + 175);
- line(WIN_HALF - 60, WIN_HALF + 175, WIN_HALF - 60, WIN_HALF + 175 + 48);
- setbkmode(TRANSPARENT);
- //左上空气湿度90%
- setTextStyle(55, 23, "Arial");
- settextcolor(BLACK);
- outtextxy(WIN_HALF - 155, 75, "90%");
- drawImg(other + 5, WIN_HALF - 90, 35); //火箭 //右上
- putimage(WIN_HALF - 90, 35, other + 5);
- setTextStyle(25, 15, "黑体");
- outtextxy(WIN_HALF - 25, 35, "空气良好");
- setTextStyle(25, 13, "宋体");
- outtextxy(WIN_HALF - 25, 65, "晴天");
- outtextxy(WIN_HALF - 25, 95, "25℃");
- outtextxy(WIN_HALF + 38, 65, "26°");
- outtextxy(WIN_HALF + 38, 95, "17°");
- drawImg(other + 4, WIN_HALF + 73, 60); //上面的箭头
- drawImg(other + 3, WIN_HALF + 73, 90); //下面的箭头
- drawImg(other + 1, WIN_HALF + 105, 70); //太阳
- putimage(WIN_HALF + 73, 60, other + 4);
- putimage(WIN_HALF + 73, 90, other + 3);
- putimage(WIN_HALF + 105, 70, other + 1);
- // 下部分
- setTextStyle(37, 17, "宋体");
- outtextxy(100, WIN_HALF + 130, "睡眠");
- outtextxy(WIN_HALF + 90, WIN_HALF + 130, "距离");
- outtextxy(50, WIN_HALF-40, "平顶山");
- setTextStyle(40, 15, "Arial");
- outtextxy(185, WIN_HALF + 125, "7h30m");
- outtextxy(215, WIN_HALF + 180, "9.88km");
- //中间
- //心率
- setTextStyle(25, 13, "宋体");
- outtextxy(60, WIN_HALF + 30, "80~128");
- drawImg(&other[0], 65, WIN_HALF + 50); //心率图
- putimage(65, WIN_HALF + 50, other + 0);
- setTextStyle(40, 15, "Arial");
- outtextxy(135, WIN_HALF + 60, "92");
- // 步数
- drawImg(&other[2], WIN_HALF + 65, WIN_HALF + 65);
- putimage(WIN_HALF + 65, WIN_HALF + 65, &other[2]);
- outtextxy(WIN_HALF + 125, WIN_HALF + 75, "9527");
- //时间、日期相关
- time_t timep = time(NULL); //获取当前时间
- struct tm* p = localtime(&timep); //把时间转成格式化时间
- setTextStyle(25, 12, "宋体");
- outtextxy(WIN_HALF + 110, WIN_HALF - 20, "四月六号");
- char fileName[40] = { 0 };
- sprintf_s(fileName, "周%s %d-%d", week[p->tm_wday], p->tm_mon + 1, p->tm_mday);
- outtextxy(WIN_HALF + 110, WIN_HALF + 10, fileName);
- // 获取字体
- setTextStyle(100, 40, "Arial");
- char szBuf[40] = { 0 };
- sprintf_s(szBuf, "%d:%02d", p->tm_hour, p->tm_min);
- outtextxy(105, 120, szBuf);
- // 秒
- setTextStyle(55, 23, "Arial");
- sprintf(szBuf, "%02d", p->tm_sec);
- outtextxy(335, 160, szBuf);
- }
- int main()
- {
- initgraph(WIN_SIZE, WIN_SIZE/*,EW_SHOWCONSOLE*/);
- SetWindowNewStyle(WIN_SIZE, WIN_SIZE);
- loadImg();
- BeginBatchDraw();//双缓冲 防止闪屏
- while (true)
- {
- gameDraw();
- animation();
- mouseEvent();
- FlushBatchDraw();
- }
- EndBatchDraw();
- return 0;
- }