C#如何绘制时钟(云服务器、云主机、高防IP、高防服务器、香港服务器、美国服务器,开发技术)

时间:2024-05-04 15:55:09 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

时钟是这样的

C#如何绘制时钟

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{//创建对象myclockMyClockmyclock=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;i<59;i++){//通过for循环来给pointf1赋值--->f1点就在圆形的边上,rfloatx1=(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;m<4;m++){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);//计算点值//点1floatx1=(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));//点2floatx2=(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);//画时针DrawHourPointer(g);//画分针DrawMinutePointer(g);//画秒针DrawSecondPointer(g);//画周和日期DrawWeeks(g);}publicboolHitTest(Pointp,Pointcenter,intr){//HitTest函数表示鼠标是否点在时钟里面//通过计算鼠标点击的点到中心点的距离和半径的比较来判定是否击中时钟//圆心到半径的距离画圆,便是圆的全部面积doublef1=(double)(p.X-center.X);doublef2=(double)(p.Y-center.Y);//test即为鼠标点击的点到中心点的距离//根据勾股定理,求距离,直角三角形a²+b²=c²doubletest=Math.Sqrt(f1*f1+f2*f2);//斜边长于圆的半径,则在圆的范围之外;斜边小于圆的半径,则在圆的范围之内if(test<=r){returntrue;}else{returnfalse;}}#region属性//此处设置成了只读--->不可写--->导致时钟的DateTime时间无法写入进来//publicDateTimeDate{get;internalset;}//publicDateTimeWeek{get;internalset;}//publicPointP{get;internalset;}//publicintR{get;internalset;}publicDateTimeDate{set{date=value;}}publicPointP{set{p=value;}}publicintR{set{r=value;}}publicDateTimeWeek{set{week=value;}}#endregion}}
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:C#如何绘制时钟的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:怎么使用JS+Canvas实现接球小游戏下一篇:

4 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18