用GDI+旋转多边形来绘制一个时钟摸拟小程序
效果图

在头文件类中声明变量
TCHAR m_dayStr[4]; // 日期
TCHAR m_weekStr[4]; // 星期
Gdiplus::Font* m_pFont; // 字体
Gdiplus::StringFormat m_strFormat; // 格式化字符串
Gdiplus::Pen* m_pPen; // 画笔
Gdiplus::SolidBrush* m_pBrush; // 画刷
Gdiplus::RectF m_dayRect; // 日期矩形
Gdiplus::RectF m_weekRect; // 星期矩形
Gdiplus::PointF m_orgPointF; // 圆点坐标
float m_rColok; //圆半径
Gdiplus::PointF hourPts[4]; //时针多边形数组
Gdiplus::PointF mimPts[4]; //分针多边形数组
Gdiplus::PointF scrPts[2]; //秒针数组
在初始化函数中初始变量的值
// 获得系统时间
SYSTEMTIME sysTime;
GetLocalTime(&sysTime); // 格式化日期和星期字符串
_stprintf_s(m_dayStr,TEXT("%02d"),sysTime.wDay); TCHAR weekStrs[7][4]={L"日",L"一",L"二",L"三",L"四",L"五",L"六"};
_stprintf_s(m_weekStr,TEXT("%s"),weekStrs[sysTime.wDayOfWeek]); // 启动时间计时器
SetTimer(m_hWnd,11,1000,NULL);
在WM_SIZE中计算圆点,半径,多边形分针,时针,秒针的顶点坐标数组值
float cx=LOWORD(lParam);
float cy=HIWORD(lParam); // 计算圆点
m_orgPointF.X=cx/2;
m_orgPointF.Y=cy/2; // 计算半径
m_rColok=min(cx,cy)/2;
m_rColok-=10; float r=m_rColok; // 秒针数组赋值
scrPts[0].X=0;
scrPts[0].Y=-r*9/10;
scrPts[1].X=0;
scrPts[1].Y=r*2/10; // 分针多边形坐标数组
mimPts[0].X=(float)(-r*0.7 / 10);
mimPts[0].Y=0;
mimPts[1].X=0;
mimPts[1].Y=-r * 8/ 10;
mimPts[2].X=(float)(r*0.7 / 10);
mimPts[2].Y=0;
mimPts[3].X=0;
mimPts[3].Y=r * 2/ 10; // 时针多边形数组
hourPts[0].X=-r / 10;
hourPts[0].Y=0;
hourPts[1].X=0;
hourPts[1].Y=-r * 6/ 10;
hourPts[2].X=r / 10;
hourPts[2].Y=0;
hourPts[3].X=0;
hourPts[3].Y=r * 2/ 10; // 日期矩形
m_dayRect.X=r-16;
m_dayRect.Y=-10;
m_dayRect.Width=20;
m_dayRect.Height=20; // 日期矩形
m_weekRect.X=r-36;
m_weekRect.Y=-10;
m_weekRect.Width=20;
m_weekRect.Height=20;
用旋转图片来绘制多边形,
图片旋转是以圆点为中心来旋转的,
所以要重新设置坐标系圆点为表盘中心点
自定义函数RotatePolygon来计算多边形的旋转,和绘制
// 旋转多边形,并绘制
// (绘制对象,多边形顶点坐标数组,顶点个数,旋转角度)
void RotatePolygon(Gdiplus::Graphics* graphics, Gdiplus::PointF* points, int numPoints, float angle) {
// 创建旋转矩阵
Gdiplus::Matrix matrix;
matrix.Rotate(angle); // 旋转多边形的每个点
Gdiplus::PointF* rotatedPoints = new Gdiplus::PointF[numPoints];
for (int i = 0; i < numPoints; i++) {
Gdiplus::PointF point = points[i];
matrix.TransformPoints(&point, 1);
rotatedPoints[i] = point;
} Gdiplus::Pen pen(Color(255,0,0,0),(numPoints==2) ? 2.0f:1.0f);
// 绘制旋转后的多边形
graphics->DrawPolygon(&pen, rotatedPoints, numPoints);
// 用线性渐变画刷填充多边形
graphics->FillPolygon(&Gdiplus::LinearGradientBrush(rotatedPoints[0],rotatedPoints[2],
Color(255,0,0,255),Color(255,255,255,0)),rotatedPoints,numPoints); delete[] rotatedPoints;
}
最后在WM_PAINT消息中绘制
void MyMainWnd::OnPaint(){
PAINTSTRUCT ps;
HDC hdc=BeginPaint(m_hWnd,&ps);
// 创建内存dc,创建内存位图,并将内存位图选入内存dc中
HDC hmdc=CreateCompatibleDC(hdc);;
HBITMAP hBitmap=CreateCompatibleBitmap(hdc,ps.rcPaint.right,ps.rcPaint.bottom);
HGDIOBJ hOldMap=SelectObject(hmdc,hBitmap);
// 创建在内存dc中绘图对象
Gdiplus::Graphics g(hmdc);
g.SetSmoothingMode(SmoothingModeAntiAlias); //设置抗锯齿模式
// 用指定颜色填充整个内存位图
m_pBrush->SetColor(Color(255,128,128,129));
g.FillRectangle(m_pBrush,0,0,ps.rcPaint.right,ps.rcPaint.bottom);
// 设置新的坐标系原点为表盘中心点
Gdiplus::Matrix transform;
transform.Translate(m_orgPointF.X, m_orgPointF.Y);
g.SetTransform(&transform);
float xBegin,yBegin;
float rClock=m_rColok; // 圆的半径
// 用指定颜色的画刷,绘制表盘上的刻度
m_pBrush->SetColor(Color(255,217,222,18));
for(int i=0;i<60;i++)
{
xBegin = (float)( rClock * sin(2 * PI*i / 60));
yBegin = (float)(rClock * cos(2 * PI*i / 60));
if (i % 5)
{
// 填充小圆点表示小刻度
g.FillEllipse(m_pBrush,xBegin-2,yBegin-2,4.0f,4.0f);
}
else
{
// 填充大圆点表示大刻度
g.FillEllipse(m_pBrush,xBegin-4,yBegin-4,8.0f,8.0f);
}
}
//获取系统时间
SYSTEMTIME x;
GetLocalTime(&x);
// 绘制显示日期和星期的矩形区域
m_pPen->SetColor(Color::Black);
m_pBrush->SetColor(Color::YellowGreen);
g.DrawRectangle(m_pPen,m_dayRect);
g.DrawRectangle(m_pPen,m_weekRect);
g.FillRectangle(m_pBrush,m_dayRect);
g.FillRectangle(m_pBrush,m_weekRect);
// 绘制日期和星期的字符串文本
m_pBrush->SetColor(Color::Black);
g.DrawString(m_dayStr,-1,m_pFont,m_dayRect,&m_strFormat,m_pBrush);
g.DrawString(m_weekStr,-1,m_pFont,PointF(m_weekRect.X+1,m_weekRect.Y+4),m_pBrush);
// 绘制时针
float tem=(float)((float)x.wMinute/60);
float fHour=x.wHour+tem;
float sita=float(fHour*30);
RotatePolygon(&g,hourPts,4,(float)sita); //计算时针旋转角度并绘制
// 绘制分针
sita=float(x.wMinute*6);
RotatePolygon(&g,mimPts,4,(float)sita);
// 绘制秒针
sita = float(x.wSecond*6);
RotatePolygon(&g,scrPts,2,sita);
// 绘制圆心
m_pBrush->SetColor(Color(255,0,0,255));
g.FillEllipse(m_pBrush,-6,-6,12,12);
// 将内存dc中绘制的图片复制到当前dc中
BitBlt(hdc,0,0,(int)ps.rcPaint.right,(int)ps.rcPaint.bottom,hmdc,0,0,SRCCOPY);
// 释放内存位图,内存dc
SelectObject(hmdc,hOldMap);
DeleteObject(hBitmap);
DeleteObject(hmdc);
EndPaint(m_hWnd,&ps);
}
用GDI+旋转多边形来绘制一个时钟摸拟小程序的更多相关文章
- 实现一个servlet的helloworld小程序(不适用Eclipse)
实现一个servlet的helloworld小程序(不适用Eclipse) 1. 在tomcat中的webapps下建一个应用程序FirstServlet(C:\tomcat\webapps\Firs ...
- 【云开发】10分钟零基础学会做一个快递查询微信小程序,快速掌握微信小程序开发技能(轮播图、API请求)
大家好,我叫小秃僧 这次分享的是10分钟零基础学会做一个快递查询微信小程序,快速掌握开发微信小程序技能. 这篇文章偏基础,特别适合还没有开发过微信小程序的童鞋,一些概念和逻辑我会讲细一点,尽可能用图说 ...
- 制作一个windows垃圾清理小程序
制作一个windows垃圾清理小程序: 把下列代码保存为.bat文件(如垃圾清理.bat) 双击它就能很快地清理垃圾文件,大约一分钟不到. 就是下面的文字(这行不用复制)=============== ...
- 使用canvas绘制一个时钟
周末学习canvas的一些基础功能,顺带写了一个基础的时钟.现在加工一下,做的更好看一点,先放上效果图: 谈一些自己的理解: (1).要绘制一个新的样式(不想被其他样式影响,或者影响到其他样式),那么 ...
- 用canvas绘制一个时钟
实现一个时钟的绘制和时间的显示 一,首先是页面的搭建html部分以及一点点的css代码,因为css这块用的比较少,所以就没有单独出来: <!DOCTYPE html> <html l ...
- 逆向工程学习第一天--一个VC6编译的小程序
今天开始研究二进制了,开个文记录一下.下面是一个小程序的OD反汇编代码,自己尝试加了注释,本人逆向零基础,属于摸着石头过河的类型,有理解错误的地方,希望大牛不吝赐教. 源代码: #include< ...
- 利用java开发一个双击执行的小程序
之前我们利用java写了很多东西,但是好像都没有什么实际意义. 因为有意义桌面小程序怎么都得有个界面,可是界面又不太好搞.或者 了解到这一层的人就少之又少了. 呀,是不是还得开辟一些版面来介绍awt和 ...
- 一个有意思的Python小程序(全国省会名称随机出题)
本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃 最近比较迷Python,仿照<Python编程快速上手>8.5写了一个随机出卷的小 ...
- 两天快速开发一个自己的微信小程序
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Songti SC" } p.p2 { margin: 0.0px 0. ...
- 使用vue+koa实现一个简单的图书小程序(1)
这个系列的博客用来记录我开发时候遇到的问题以及学习到的知识 边做边学: 前后端分离,高内聚低耦合小程序端使用了mpvue 内部使用了vuejs的语法 来做整个小程序的渲染层 后端使用的是koa2搭建一 ...
随机推荐
- 浮点数格式:FP64, FP32, FP16, BFLOAT16, TF32之间的相互区别
浮点数格式 (参考1,参考2) 浮点数是一种用二进制表示的实数,它由三个部分组成:sign(符号位).exponent(指数位)和fraction(小数位).不同的浮点数格式有不同的位数分配给这三个部 ...
- UART和RS232、RS485的关系是什么?
串口通讯是电子工程师和嵌入式开发工程师面对的最基本问题,RS232则是其中最简单最常用的通讯方式.但是初学者往往搞不清有关的名词如UART和RS232或RS485之间是什么关系,因为它们经常被放到语句 ...
- 设备树DTS 学习:3-驱动开发中常用的 DTS api
背景 本章的内容是为了实现在驱动中的开发,通过调用有关的api来寻找设备树节点熟悉,从而达到使用设备树进行驱动开发的目的. 参考:Linux内核 设备树操作常用API Linux设备树语法详解一文中介 ...
- 【基础计算】ESDF栅格距离图计算并行加速版
前言与参考 这一部分仅为路径规划源码及论文GPIR的一个小部分,但是有代码实现,第一次看的时候有些懵,所以特此记录:主要是设置好了栅格地图后,添加了障碍物后,对其的欧式距离计算和梯度计算等.原代码中为 ...
- 全国产T3+FPGA的SPI与I2C通信方案分享
近年来,随着中国新基建.中国制造2025规划的持续推进,单ARM处理器越来越难胜任工业现场的功能要求,特别是如今能源电力.工业控制.智慧医疗等行业,往往更需要ARM + FPGA架构的处理器平台来实现 ...
- Linux系统用户组管理
用户管理 和Windows一样在Linux中也存在许多用户,可以登陆Linux,和Windows不同的是,在Windows中同一时刻只可以存在一个用户登录系统,而在Linux中是允许多个用户同时登 ...
- win10: pyinstaller在python2和python3环境下的适应性配置
win10:pyinstaller在python2和python3环境下的适应性配置 前言 pyinstaller是一个非常优秀的python可执行程序打包工具,在windows下打包成.exe文件, ...
- Springboot+Shiro+Mybatis+mysql实现权限安全认证
Shiro是Apache 的一个强大且易用的Java安全框架,执行身份验证.授权.密码学和会话管理.Shiro 主要分为两个部分就是认证和授权两部分 一.介绍 Subject代表了当前用户的安全操作 ...
- Spring DI(依赖注入)自动装配 @Autowired、@Resource注解
@Autowired:一部分功能是查找实例,从Spring容器中根据类型(Java类)获取对应的实例:另一部分功能就是赋值,将找到的实例,装配给另一个实例的属性值.(注:一个Java类型在同一个Spr ...
- webpack性能优化方式之dll--- webpack.dll.config.js
通常来说,我们的代码都可以至少简单区分成业务代码和第三方库.如果不做处理,每次构建时都需要把所有的代码重新构建一次,耗费大量的时间.然后大部分情况下,很多第三方库的代码并不会发生变更(除非是版本升级) ...