C#时钟控件

图形图像软件编程 同时被 2 个专栏收录
24 篇文章 2 订阅
105 篇文章 0 订阅

多年前写的时钟控件,发布出来,供大家参考。

先看效果:

首先,制作一个从UserControl继承的时钟控件,使用双缓冲绘制。由于是几年前的水平,一些代码写到了属性中,也懒得再改了,感兴趣的,可以改得更规范些。

//ClockControl.cs

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace BrawDraw.Com.PhotoFrame.Net.PublicFunctions
{
 public class ClockControl: UserControl
 {
  DateTime dt;
  Pen      pen   = new Pen(Color.Black, 1);
  Pen      penSecond   = new Pen(Color.Black, 6);
  Brush    brush = new SolidBrush(Color.Black);
  Bitmap m_Bitmap = null;
  Graphics g = null;
  private Font ClockFont = new Font("Arial", 48, FontStyle.Bold);

  public ClockControl()
  {
   SetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw, true);
   this.UpdateStyles();
   Enabled = false;
   m_Bitmap = new Bitmap(100, 100);
  }

  public DateTime Time
  {
   get
   {
    return dt; 
   }
   set
   {
    m_Bitmap = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
    g = Graphics.FromImage(m_Bitmap);
    g.Clear(Color.White);
    InitializeCoordinates(g);

    DrawDots(g, brush);
    DrawHourHand(g, pen);
    DrawMinuteHand(g, pen);
    DrawNumbers(g);
    // DrawSecondHand(g, pen);
    // if(g != null) g.Dispose();
    if (dt.Hour != value.Hour)
    {
     DrawHourHand(g, pen);
    }
    if (dt.Minute != value.Minute)
    {
     DrawHourHand(g, pen);
     DrawMinuteHand(g, pen);
    }
    if (dt.Second != value.Second)
    {
     DrawMinuteHand(g, pen);
     DrawSecondHand(g, pen);
    }
    if (dt.Millisecond != value.Millisecond)
    {
     DrawSecondHand(g, pen);
    }         
    dt  = value;
    
    Graphics grfx = CreateGraphics();
    grfx.DrawImage(m_Bitmap, 0, 0);
    this.Validate();
    if(grfx != null) grfx.Dispose();
   }
  }

  protected override void OnPaint(PaintEventArgs pea)
  {
   g  = pea.Graphics;
   g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
   g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
   DrawClock(g);
   base.OnPaint (pea);
  }

  private void DrawClock(Graphics gg)
  {
   m_Bitmap = new Bitmap(this.Width, this.Height);
   Graphics grfx = Graphics.FromImage(m_Bitmap);
   grfx.Clear(Color.White);
   InitializeCoordinates(grfx);
   DrawDots(grfx, brush);
   DrawHourHand(grfx, pen);
   DrawMinuteHand(grfx, pen);
   DrawSecondHand(grfx, pen);
   DrawNumbers(grfx);
   gg.DrawImage(m_Bitmap, 0, 0);
   grfx.Dispose();
  }

  void InitializeCoordinates(Graphics grfx)
  {
   if (Width == 0 || Height == 0) return;

   grfx.TranslateTransform(Width / 2, Height / 2);

   float fInches = Math.Min(Width / grfx.DpiX, Height / grfx.DpiY);

   grfx.ScaleTransform(fInches * grfx.DpiX / 2000,
    fInches * grfx.DpiY / 2000);
  }

  void DrawDots(Graphics grfx, Brush brush)
  {
   for (int i = 0; i < 60; i++)
   {
    int iSize = i % 5 == 0 ? 100 : 30;

    grfx.FillEllipse(brush, 0 - iSize / 2, - 860 - iSize / 2, iSize, iSize);
    grfx.RotateTransform(6);
   }         
  }

  protected virtual void DrawHourHand(Graphics grfx, Pen pen)
  {
   GraphicsState gs = grfx.Save();
   grfx.RotateTransform(360f * Time.Hour / 12 + 30f * Time.Minute / 60 + 2);

   grfx.DrawPolygon(pen, new Point[]
         {
          new Point(0,  150), new Point( 100, 0),
          new Point(0, -600), new Point(-100, 0)
         });
   grfx.Restore(gs);
  }

  protected virtual void DrawMinuteHand(Graphics grfx, Pen pen)
  {
   GraphicsState gs = grfx.Save();
   grfx.RotateTransform(360f * Time.Minute / 60 +
    6f * Time.Second / 60 + 2);

   grfx.DrawPolygon(pen, new Point[]
         {
          new Point(0,  200), new Point( 50, 0),
          new Point(0, -800), new Point(-50, 0)
         });
   grfx.Restore(gs);
  }

  protected virtual void DrawSecondHand(Graphics grfx, Pen pen)
  {
   GraphicsState gs = grfx.Save();
   grfx.RotateTransform(360f * Time.Second / 60 + 6f * Time.Millisecond / 1000 + 2.8f);

   grfx.DrawLine(penSecond, 0, 0, 0, -800);
   grfx.Restore(gs);         
  }

  private void InitializeComponent()
  {
   //
   // ClockControl
   //
   this.Name = "ClockControl";
   this.Size = new System.Drawing.Size(416, 424);

  }

  protected void DrawNumbers(Graphics grfx)
  {
   int count = 1;
   int r = 1900;
   int dx = 25;
   int dy = 20;
   int offset = 8;
   int dr = 300;
   GraphicsState gs = grfx.Save();
   grfx.TranslateTransform(- r/2 - dx, - r/2 - dy);

   grfx.DrawEllipse(new Pen(Color.Black, 10), dx / 2 + offset, dy / 2 + offset, r + dx - offset, r + dy - offset);
   //grfx.DrawEllipse(new Pen(Color.Black, 2), dx + offset, dy + offset, r - offset, r - offset);

   grfx.TranslateTransform(dr/3 + 15, dr/3 + 15);
   for (double a = 0; a < 2 * Math.PI; a += (2.0* Math.PI/12))
   {
    double x = (r - dr * 1.2)/2 * Math.Cos(a - Math.PI/3) + (r - dr)/2 + 25;
    double y = (r - dr * 1.2)/2 * Math.Sin(a - Math.PI/3)+ (r - dr)/2 + 20;
    grfx.DrawString(Convert.ToString(count), ClockFont, Brushes.Black, (float)x,(float)y, new StringFormat());
    count++;
   }
   
   grfx.Restore(gs);
   //grfx.DrawLine(new Pen(Color.Black, 1), 0, -800, 0, 800);
  }
 }
}

接着再从BezierClockControl再从 ClockControl控件继承,由于绘制方式不同,因此最后显示的效果也不同:

//BezierClockControl.cs

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace BrawDraw.Com.PhotoFrame.Net.PublicFunctions
{
 public class BezierClockControl: ClockControl
 {
  protected override void DrawHourHand(Graphics grfx, Pen pen)
  {
   GraphicsState gs = grfx.Save();
   grfx.RotateTransform(360f * Time.Hour / 12 +
    30f * Time.Minute / 60);
   GraphicsPath gp = new GraphicsPath();
   Point[] points = new Point[]
    {
     new Point(  0, -600), new Point(   0, -300),
     new Point(200, -300), new Point(  50, -200),
     new Point( 50, -200), new Point(  50,    0),
     new Point( 50,    0), new Point(  50,   75),
     new Point(-50,   75), new Point( -50,    0),
     new Point(-50,    0), new Point( -50, -200),
     new Point(-50, -200), new Point(-200, -300),
     new Point(  0, -300), new Point(   0, -600)
    };
   gp.AddBeziers(points);
   //grfx.DrawBeziers(pen, points);
   grfx.FillPath(new SolidBrush(Color.Red), gp);
   grfx.Restore(gs);
   gp.Dispose();
  }

  private void InitializeComponent()
  {
   //
   // BezierClockControl
   //
   this.Name = "BezierClockControl";
   this.Size = new System.Drawing.Size(448, 376);

  }

  protected override void DrawMinuteHand(Graphics grfx, Pen pen)
  {
   GraphicsState gs = grfx.Save();
   grfx.RotateTransform(360f * Time.Minute / 60 +
    6f * Time.Second / 60);
   GraphicsPath gp = new GraphicsPath();
   Point[] points = new Point[]
    {
     new Point(  0, -800), new Point(   0, -750),
     new Point(  0, -700), new Point(  25, -600),
     new Point( 25, -600), new Point(  25,    0),
     new Point( 25,    0), new Point(  25,   50),
     new Point(-25,   50), new Point( -25,    0),
     new Point(-25,    0), new Point( -25, -600),
     new Point(-25, -600), new Point(   0, -700),
     new Point(  0, -750), new Point(   0, -800)
    };
   gp.AddBeziers(points);
   grfx.FillPath(new SolidBrush(Color.Green), gp);
   //grfx.DrawBeziers(pen, points);
   grfx.Restore(gs);
   gp.Dispose();
  }
 }
}

 

最后,我们来测试一下:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace BrawDraw.Com.PhotoFrame.Net.PublicFunctions
{
 /// <summary>
 /// BezierClock 的摘要说明。
 /// </summary>
 public class BezierClock : System.Windows.Forms.Form
 {
  /// <summary>
  /// 必需的设计器变量。
  /// </summary>
  private System.ComponentModel.Container components = null;
  //ClockControl clkctl;
  BezierClockControl clkctl;

  public BezierClock()
  {
   InitializeComponent();
   this.SetStyle(ControlStyles.DoubleBuffer, true);
   this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
   // Redraw when resized
   this.SetStyle(ControlStyles.ResizeRedraw, true);

   Text = "Bezier Clock";
   //clkctl = new ClockControl();
   clkctl = new BezierClockControl();
   clkctl.Parent    = this;
   clkctl.Time      = DateTime.Now;
   clkctl.Dock      = DockStyle.Fill;
   clkctl.BackColor = Color.Black;
   clkctl.ForeColor = Color.White;

   Timer timer = new Timer();
   timer.Interval = 1000;
   timer.Tick += new EventHandler(OnTimerTick);
   timer.Start();
  }

  void OnTimerTick(object obj, EventArgs ea)
  {
   clkctl.Time = DateTime.Now;
  }
  
  /// <summary>
  /// 清理所有正在使用的资源。
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null)
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }

  #region Windows 窗体设计器生成的代码
  /// <summary>
  /// 设计器支持所需的方法 - 不要使用代码编辑器修改
  /// 此方法的内容。
  /// </summary>
  private void InitializeComponent()
  {
   //
   // BezierClock
   //
   this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
   this.ClientSize = new System.Drawing.Size(432, 421);
   this.Name = "BezierClock";
   this.Text = "BezierClock";

  }
  #endregion

  /// <summary>
  /// 应用程序的主入口点。
  /// </summary>
  [STAThread]
  static void Main()
  {
   Application.Run(new BezierClock());
  }
 }
}

 源码及相关文件已上传至CSDN下载资源库中,大家有兴趣可以下载,下载地址是:http://download.csdn.net/detail/johnsuna/4977486

  • 2
    点赞
  • 1
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

C#写的闹钟应用程序。到处都是注释,一看就懂! 核心代码和效果展示见我的博客:http://blog.csdn.net/luochao5862426/article/details/78570141 个人特色: 1、可以这么所说,别人有的,我有!别人没有的,我也有。集百家之长,选我就对了,嘿嘿。 2、代码详细,基本上每一条稍微重要点的代码都有注释这行代码是干嘛的,所以你可以看到好多好多注释,详细的不能再详细! 3、里面包含,可直接导入的项目文件、该程序的PPT展示以及录制的视频展示。 4、模块清晰,注释详细,低耦合,高内聚。 主页面介绍:分三个部分 一、动态时钟部分,像石英钟一样时、分、秒针不停转动。 二、定点闹钟部分,简单点就是可以定闹钟。 三、闹钟备忘录部分,显而易见,为了添加提示功能。 本人设计了两种可选模式: 1、懒人模式(可多次延时响铃,下面主要讲述这个模式) 2、生存模式(本次考验失败后则下次的闹钟提前几分钟响铃。由于时间有限本人没去实现这个功能) 主要功能介绍: 一、时钟(石英钟) 1、使用C#的GDI+画出石英钟时、分、秒针不停转动的效果并加上了指针的尾巴。 二、闹钟 1、定闹钟时添加备注。 2、自选(默认铃声或本地铃声)试听铃声。所以机智的你可以当一个MP3用了。 3、设定多个闹钟。重点是,你可以设置不同类型(今天、每天、自定义星期、指定日期)的闹钟。 4、设定不同的响铃方式。包括:只响一次、不断响铃、静音响铃。 5、定时关机。定闹钟的时候选择了定时关机这个选项,那么,在闹钟到点后的一定时间内(我设置的3秒)会自动关机。 6、开机自启动。这个可以自己设定,很多人不需要。 7、响铃抖屏。闹钟到点后会抖动一小段时间(我设置的3秒)的屏幕,并同步跳到你打开的所有窗口的最顶层窗体。 8、系统托盘。可以隐藏到系统托盘。 三、备忘录 {备忘录组成:时段+时间+备注+尾巴(可删除,知识为了查看有哪些操作)} 1、移除所定的闹钟。 2、把闹钟备忘录保存至本地。 3、从本地导入至闹钟备忘录。所以你可以在本地修改备忘录咯,包括时间和内容。 4、修改闹钟备忘录内容。在程序界面修改备忘录。 5、查找备忘录内容。在程序界面查找备忘录内容。 6、显示倒计时。你在定闹钟的时候要是选了倒计时这个选项,则你可以在备忘录里面选中,显示倒计时。
©️2021 CSDN 皮肤主题: 成长之路 设计师:Amelia_0503 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值