版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第C#绘制时钟的方法本文实例为大家分享了使用C#写一个时钟,供大家参考,具体内容如下
时钟是这样的
一共使用四个控件即可:
WinFrom窗体应用程序代码:
usingSpeechLib;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Drawing.Drawing2D;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
usingSystem.Windows.Forms;
namespaceMyClockTest
publicpartialclassForm1:Form
{
//创建对象myclock
MyClockmyclock=newMyClock();
//定义date1,共电子表使用--获取到当下时间点
DateTimedate1=DateTime.Now;//Now为静态只读属性(属性可计算)
//定义中心点center和半径radius--时钟的圆心和半径大小
Pointcenter=newPoint(160,200);//圆心点的坐标
intradius=150;//半径150
//定义判定是否击中表盘的bool变量--鼠标点击拖拽功能
booldown=false;
//记录鼠标点击的点
Pointpre;
//程序入口
publicForm1()
{
InitializeComponent();
}
//开始画时钟
privatevoidOnPaint(objectsender,PaintEventArgse)
{
//这里不使用Graphics,而选择使用BufferedGraphics:
//Graphics和BufferedGraphics对比:
//5000次下时Graphics效率高一些;5000次以后BufferedGraphics效率高一些
//Bitmapbmp=newBitmap(width,height);
//Graphicsg2=Graphics.FromImage(bmp);
//myclock.Draw(g2);
//g2.CreateGraphics();
//g2.DrawImage(bmp,0,0);
//bmt.dispose();
//Imageiamge=newBitmap(this.Width,this.Height);
//Graphicsg1=Graphics.FromImage(iamge);
//g1.Clear(Form.DefaultBackColor);
//C#双缓冲解释:
//简单说就是当我们在进行画图操作时,系统并不是直接把内容呈现到屏幕上,而是先在内存中保存,然后一次性把结果输出来。
//如果没用双缓冲的话,你会发现在画图过程中屏幕会闪的很厉害,因为后台一直在刷新,
//而如果等用户画完之后再输出就不会出现这种情况,具体的做法,其实也就是先创建一个位图对象,然后把内容保存在里面,最后把图呈现出来。
//解决空间重绘时闪烁的问题,并在改变大小时重绘图形
this.SetStyle(ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw|ControlStyles.AllPaintingInWmPaint,true);
//矩形绘图区域
Rectanglerect=e.ClipRectangle;
//关于BufferedGraphicsContext类:
//
手工设置双缓冲.netframework提供了一个类BufferedGraphicsContext负责单独分配和管理图形缓冲区。
//
每个应用程序域都有自己的默认BufferedGraphicsContext实例来管理此应用程序的所有默认双缓冲。
//
大多数情况下,每个应用程序只有一个应用程序域,所以每个应用程序通常只有一个默认BufferedGraphicsContext。
//关于此处的绘图:
//通过管理BufferedGraphicsContext实现双缓冲的步骤如下:
//(1)获得对BufferedGraphicsContext类的实例的引用。
//(2)通过调用BufferedGraphicsContext.Allocate方法创建BufferedGraphics类的实例。
//(3)通过设置BufferedGraphics.Graphics属性将图形绘制到图形缓冲区。
//(4)当完成所有图形缓冲区中的绘制操作时,可调用BufferedGraphics.Render方法将缓冲区的内容呈现到与该缓冲区关联的绘图图面或者指定的绘图图面。
//(5)完成呈现图形之后,对BufferedGraphics实例调用释放系统资源的Dispose方法。
BufferedGraphicsContextcurrent=BufferedGraphicsManager.Current;//(1)
BufferedGraphicsbg;
bg=current.Allocate(e.Graphics,e.ClipRectangle);//(2)
Graphicsg=bg.Graphics;//(3)
//定义画布
//Graphicsg=CreateGraphics();
//消除锯齿
//g.SmoothingMode=SmoothingMode.AntiAlias;
g.SmoothingMode=SmoothingMode.HighQuality;//高质量
g.PixelOffsetMode=PixelOffsetMode.HighQuality;//高像素偏移质量
//每次绘画后的背景色填充定义画电子钟的字体
g.Clear(this.BackColor);
Fontfont=newFont("TimesNewRoman",20);
//在每次绘画时,更新时间,半径及中心点
myclock.Date=DateTime.Now;
myclock.Week=DateTime.Now;
myclock.P=center;
myclock.R=radius;
//调用myclock中的Draw函数画出钟
myclock.Draw(g);
//直接调用DrawString函数,显示电子表,并且设置显示格式
g.DrawString(date1.ToString(),font,Brushes.Black,10,10);//10,10表示字的左上角在哪
bg.Render(e.Graphics);//(4)---开启绘制
bg.Dispose();//(5)---绘制完成,释放资源
//如果为整点,则报时
if(Convert.ToString(DateTime.Now.Minute)=="0"Convert.ToString(DateTime.Now.Second)=="0")
{
SpVoicevoice=newSpVoice();
voice.Speak("现在时间为"+Convert.ToString(DateTime.Now.Month)+"月"+Convert.ToString(DateTime.Now.Day)+"日"+Convert.ToString(DateTime.Now.Hour)+"点"+Convert.ToString(DateTime.Now.Minute)+"分",SpeechVoiceSpeakFlags.SVSFDefault);
}
}
//更新时钟的时间
privatevoidOnTime(objectsender,EventArgse)
{
//使用timer控件来更新时间---1s/次
//更新钟的时间
myclock.Date=DateTime.Now;
myclock.Week=DateTime.Now;
//更新电子表的时间
date1=DateTime.Now;
//刷新---每走动一秒都更新画布(重绘)
Invalidate();
//Refresh();
}
//鼠标单击到时钟上的坐标
privatevoidForm1_MouseDown(objectsender,MouseEventArgse)
{
//记录点击的点,并且计算是否击中时钟--记录点击时的坐标
pre=newPoint(e.X,e.Y);
down=myclock.HitTest(pre,center,radius);
}
//在点击后,鼠标拖动时
privatevoidForm1_MouseMove(objectsender,MouseEventArgse)
{
//使用if来判断是否击中,若击中,更新中心点
Pointp=newPoint(e.X,e.Y);
//如果点击持续
if(down)
{
//更新圆心坐标点
center=newPoint(center.X+p.X-pre.X,center.Y+p.Y-pre.Y);
//pre=当前移动的点的坐标
pre=p;
//重绘
Invalidate();
//Refresh();
}
}
privatevoidForm1_MouseUp(objectsender,MouseEventArgse)
{
//取消击中--拖拽结束
down=false;
}
privatevoidtrackBar1_Scroll(objectsender,EventArgse)
{
//使用trackBar1来控制半径大小,并且更新---trackBar控件改变时钟的大小
radius=trackBar1.Value;
Invalidate();
//refresh
}
//单击:报时功能
privatevoidbutton1_Click(objectsender,EventArgse)
{
DateTimeda=newDateTime();
da=DateTime.Now;
//SpVoice报时
SpVoicevoice=newSpVoice();
voice.Speak("现在时间为"+Convert.ToString(da.Month)+"月"+Convert.ToString(da.Day)+"日"+Convert.ToString(da.Hour)+"点"+Convert.ToString(da.Minute)+"分",SpeechVoiceSpeakFlags.SVSFDefault);
}
}
//初始化时钟:类应该写在外面(此处不规范)
publicclassMyClock
{
enumtime{XII,III,VI,IX}//定义结构体--时钟的4顶点
publicDateTimedate;//Now为静态只读{get}属性(属性可计算),智能作为右值--电子表时间
publicDateTimeweek;//周
publicPointp;//圆心点的坐标
publicintr;//半径
publicMyClock()
{
//定义一个构造函数,赋予date当前时间
date=DateTime.Now;
week=DateTime.Now;
p=newPoint(160,200);//圆心点的坐标
r=150;//半径
}
//画表盘
publicvoidDrawDial(Graphicsg)
{
//定义两个pen,p1用来画小刻度及表盘,p2用来画大刻度
Penp1=newPen(Color.Black,2);
Penp2=newPen(Color.Green,2);
//时钟顶点时间的字体大小
floatf=r/10;
//字体样式字体大小
Fontfont=newFont("TimesNewRoman",f);
//定义两个点数组来存储刻度线的两点---[60]数组中共存放了60个点的坐标
PointF[]pointf1=newPointF[60];
PointF[]pointf2=newPointF[60];
//
for(inti=0;ii++)
{
//通过for循环来给pointf1赋值---f1点就在圆形的边上,r
floatx1=(float)(p.X+r*Math.Sin((i+1)*Math.PI*2/60));
floaty1=(float)(p.Y+r*Math.Cos((i+1)*Math.PI*2/60));
pointf1[i]=newPointF(x1,y1);
//使用if来判断,能整除5就画大刻度,不能就画小刻度
if((i+1)%5==0)
{
floatx2=(float)(p.X+(r-r/20)*Math.Sin((i+1)*2*Math.PI/60));
floaty2=(float)(p.Y+(r-r/20)*Math.Cos((i+1)*2*Math.PI/60));
pointf2[i]=newPointF(x2,y2);
//画大刻度
g.DrawLine(p2,pointf1[i],pointf2[i]);
}
else
{
floatx2=(float)(p.X+(r-r/40)*Math.Sin((i+1)*2*Math.PI/60));
floaty2=(float)(p.Y+(r-r/40)*Math.Cos((i+1)*2*Math.PI/60));
pointf2[i]=newPointF(x2,y2);
//画小刻度
g.DrawLine(p2,pointf1[i],pointf2[i]);
}
}
//用pointf3来储存四个点的位置表盘的4个顶点位置---横坐标纵坐标调整距离到合适的位置上
PointF[]pointf3=
{
newPointF(pointf1[30].X-f/4,pointf1[30].Y+r/20),
newPointF(pointf1[15].X-r/20-2*f,pointf1[15].Y+f/3),
newPointF(pointf1[0].X-2*f,pointf1[0].Y-r/20-4*f/3),
newPointF(pointf1[45].X+r/20,pointf1[45].Y-r/20-4*f/3),
};
//画出四个点相应的时间值
for(intm=0;mm++)
{
g.DrawString(((time)m).ToString(),font,Brushes.Black,pointf3[m]);
}
//代码重复---代码保持高内聚低耦合---(time)将阿拉伯数字改成时间类型
//g.DrawString(((time)0).ToString(),font,Brushes.Black,pointf3[0]);
//g.DrawString(time.III.ToString(),font,Brushes.Black,pointf3[1]);
//g.DrawString(time.VI.ToString(),font,Brushes.Black,pointf3[2]);
//g.DrawString(time.IX.ToString(),font,Brushes.Black,pointf3[3]);
//使用DrawEllipse画表盘---pen左上角的x坐标左上角的y坐标宽度高度---画圆
g.DrawEllipse(p1,p.X-r,p.Y-r,2*r,2*r);
}
//画时针
publicvoidDrawHourPointer(Graphicsg)
{
//定义画笔p1,设置其属性,使其带有箭头,圆点尾部
Penp1=newPen(Color.Green,4);
p1.EndCap=LineCap.ArrowAnchor;//箭头
p1.StartCap=LineCap.Round;//尾部
//获取分钟,转化为int型
inti=Convert.ToInt32(date.Minute);
//获取小时,并转换为int型,同时对12取余,获得十二小时制的小时数
intj=(Convert.ToInt32(date.Hour))%12;
//计算点值---(2*Math.PI)*j/720)根据分钟表示时针的位置---1分钟再小时里占比1/720---60分钟*12个小时数=720
//点1的坐标
floatx1=(float)(p.X+(r-r/3)*Math.Sin((j*2*Math.PI/12)+(2*Math.PI)*i/720));
floaty1=(float)(p.Y-(r-r/3)*Math.Cos((j*2*Math.PI/12)+(2*Math.PI)*i/720));
//点2的坐标
floatx2=(float)(p.X-r/30*Math.Sin((j*2*Math.PI/12)+(2*Math.PI)*i/720));
floaty2=(float)(p.Y+r/30*Math.Cos((j*2*Math.PI/12)+(2*Math.PI)*i/720));
PointFpointf1=newPointF(x1,y1);
PointFpointf2=newPointF(x2,y2);
//用DrawLine画时针
g.DrawLine(p1,pointf2,pointf1);
}
//画分针
publicvoidDrawMinutePointer(Graphicsg)
{
//定义画笔p1,设置其属性,使其带有箭头,圆点尾部
//画笔宽度为3---分针比时针细一点
Penp1=newPen(Color.Blue,3);
p1.EndCap=LineCap.ArrowAnchor;
p1.StartCap=LineCap.Round;
//获取当前分钟,并转换为int型
inti=Convert.ToInt32(date.Minute);
//计算点值
//点1
floatx1=(float)(p.X+(r-r/5)*Math.Sin(i*2*Math.PI/60));
floaty1=(float)(p.Y-(r-r/5)*Math.Cos(i*2*Math.PI/60));
//点2
floatx2=(float)(p.X-r/20*Math.Sin(i*2*Math.PI/60));
floaty2=(float)(p.Y+r/20*Math.Cos(i*2*Math.PI/60));
PointFpointf1=newPointF(x1,y1);
PointFpointf2=newPointF(x2,y2);
//用DrawLine画分针
g.DrawLine(p1,pointf2,pointf1);
}
//画秒针
publicvoidDrawSecondPointer(Graphicsg)
{
Penp1=newPen(Color.Red,2);
p1.EndCap=LineCap.ArrowAnchor;
p1.StartCap=LineCap.Round;
//获取当前秒,并转换为int型
inti=Convert.ToInt32(date.Second);
//计算点值
floatx1=(float)(p.X+(r-r/20)*Math.Sin(i*2*Math.PI/60));
floaty1=(float)(p.Y-(r-r/20)*Math.Cos(i*2*Math.PI/60));
floatx2=(float)(p.X-r/15*Math.Sin(i*2*Math.PI/60));
floaty2=(float)(p.Y+r/15*Math.Cos(i*2*Math.PI/60));
PointFpointf1=newPointF(x1,y1);
PointFpointf2=newPointF(x2,y2);
//用DrawLine画秒针---根据两点之间画线
g.DrawLine(p1,pointf2,pointf1);
}
//周和日期显示---
表盘上
publicvoidDrawWeeks(Graphicsg)
{
//字体大小
floatf=r/15;
Fontfont=newFont("TimesNewRoman",f);
//放置位置
floatf1=(float)(p.X+r*Math.Sin(Math.PI)/2);
floatf2=(float)(p.Y-r*Math.Cos(Math.PI)/2);
//DrawString---画字符串
g.DrawString(week.DayOfWeek.ToString(),font,Brushes.Black,f1,f2);
g.DrawString(week.Day.ToString(),font,Brushes.Black,f1+80,f2);
}
publicvoidDraw(Graphicsg)
{
//定义函数Draw,画出时钟
//画表盘
DrawDial(g);
//画时针
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 浙江临安农村商业银行股份有限公司2027届校园招聘笔试参考题库及答案解析
- 2026年湖北省宜昌市公务员人员招聘考试参考试题与答案详解
- 某水泥厂节能降耗规范
- 2026四川内江经开区就业和社会保障服务中心招聘见习人员1人笔试参考题库及答案解析
- 2026山东淄博职业技术大学高层次人才招聘13人(第二批)考试备考题库及答案解析
- 2026年福建省五建建设集团有限公司招聘第二批工作人员9人考试模拟试题及答案解析
- 2026年芜湖智能传感器研究院有限公司专业技术人才招聘部分岗位补招笔试模拟试题及答案解析
- 2026年浙江省台州市公务员人员招聘笔试参考试题与答案详解
- 2026宁电投(石嘴山市)能源发展有限公司秋季招聘30人考试模拟试题及答案解析
- 2026重庆水利电力职业技术学院考核招聘事业单位人员(第二批)8人考试备考试题及答案解析
- 2026客服面试题及参考答案
- 2026秋小学苏教版科学四年级上册第三单元学情测试练习卷含答案三套
- 2027贵州航天电器秋季招聘284人考试模拟试题及答案解析
- 2026年高级园林绿化工职业技能鉴定理论考试题库及答案
- 第6课 人民当家作主 第1课时 课件(内嵌视频)2026-2027学年道德与法治五年级上册统编版
- 2026年初级车险理赔试题及答案
- 光伏发电并网工程接入系统设计方案
- 《新能源汽车电工电子技术》课程标准
- 中医胆囊结石护理要点说课
- 2026中国机床检测市场投资前景研究与可持续发展规划研究报告
- 2026年医疗器械基础知识培训资料
评论
0/150
提交评论