C#时钟控件

来源:互联网 发布:淘宝卖家加入花呗条件 编辑:程序博客网 时间:2024/05/17 09:13

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

先看效果:

首先,制作一个从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

原创粉丝点击