使用C#编写LED样式时钟控件

来源:岁月联盟 编辑:zhu 时间:2006-03-21
//--------------------------(如转载,请保留版权信息)-------------------------//
//   SevenSegmentClockStyle.cs 朱继山 a3news(AT)hotmail.com  --//
// ----------------------------- http://www.brawdraw.com ----------------------//
// -------------------- 未经书面许可,请勿用于商业用途 ---------------------//

using System;

namespace BrawDraw.Com.PhotoFrame.Net.PublicFunctions.Clock
{
 /// <summary>
 /// Clock's Style.时钟的样式定义
 /// </summary>
 public enum SevenSegmentClockStyle
 {
  DateOnly, // 只显示日期
  TimeOnly, // 只显示时间
  DateAndTime //显示日期和时间
 }
}

//--------------------------(如转载,请保留版权信息)-------------------------//
//    SevenSegmentClock.cs  朱继山 a3news(AT)hotmail.com  -------//
// ----------------------------- http://www.brawdraw.com ----------------------//
// -------------------- 未经书面许可,请勿用于商业用途 ---------------------//
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Windows.Forms;
using BrawDraw.Com.PhotoFrame.Net.PublicFunctions;
using System.ComponentModel;

namespace BrawDraw.Com.PhotoFrame.Net.PublicFunctions.Clock
{
//这是控件的关键代码
 public class SevenSegmentClock : UserControl
 {
  DateTime _dateTime;
//默认使用同时绘制日期和时间
  SevenSegmentClockStyle _clockStyle = SevenSegmentClockStyle.DateAndTime;
  Color _clockColor = Color.Black;
//是否绘制阴影(即残影),以摸拟真似的LED时钟
  bool _isDrawShadow = true;

  Timer _timer    = null;
//是否自动更新时间
  bool _isTimerEnable = false;
  Graphics g = null;
  Bitmap m_Bitmap = null;

  public bool IsDrawShadow
  {
   get { return this._isDrawShadow; }
   set
   {
    this._isDrawShadow = value;
    this.Invalidate();
   }
  }

  [Browsable(false)]
  public System.Windows.Forms.Timer Timer
  {
   get { return this._timer; }
   set
   {
    this._timer = value;
    if(_timer != null)
    {
     _timer.Tick    += new EventHandler(TimerOnTick);
    }
   }
  }

  public bool IsTimerEnable
  {
   get { return this._isTimerEnable; }
   set
   {
    if(value == true)
    {
     if(this._timer == null)
     {
      _timer = new Timer();
      _timer.Tick    += new EventHandler(TimerOnTick);
      _timer.Interval = 1000;
      _timer.Enabled  = true;
     }
    }
    else
    {
     if(this._timer != null)
     {
      _timer.Enabled  = false;
     }
    }
    this._isTimerEnable = value;
   }
  }

  public void Start()
  {
   this.IsTimerEnable = true;
   this.Refresh();
  }

  public void Stop()
  {
   this.IsTimerEnable = false;
  }

  public System.DateTime DateTime
  {
   get { return this._dateTime; }
   set { this._dateTime = value; }
  }

//LED文字的颜色
  public System.Drawing.Color ClockColor
  {
   get { return this._clockColor; }
   set
   {
    this._clockColor = value;
    this.Invalidate();
   }
  }

  public SevenSegmentClockStyle SevenSegmentClockStyle
  {
   get { return this._clockStyle; }
   set
   {
    this._clockStyle = value;
    this.Invalidate();
   }
  }

  public SevenSegmentClock()
  {
   Text = "Seven-Segment Clock";
//使用双缓冲,支持透明绘制
   SetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint
    | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true);
   this.UpdateStyles();
   Init();
   _dateTime = DateTime.Now;
  }

//初始化
  private void Init()
  {
   m_Bitmap = new Bitmap(this.Width, this.Height);

   g = Graphics.FromImage(m_Bitmap);
   g.CompositingQuality = CompositingQuality.HighQuality;
   g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
   
   //g.InterpolationMode = InterpolationMode.HighQualityBicubic;
   g.SmoothingMode = SmoothingMode.HighQuality;
   //g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
  }

  void TimerOnTick(object obj, EventArgs ea)
  {
   DateTime dtNow = DateTime.Now;
   dtNow = new DateTime(dtNow.Year, dtNow.Month, dtNow.Day, dtNow.Hour, dtNow.Minute, dtNow.Second);
   if (dtNow != _dateTime)
   {
    _dateTime = dtNow;
    Invalidate();
   }
  }

  protected override void OnPaint(PaintEventArgs e)
  {
   m_Bitmap = DrawClock();
   Graphics gg = e.Graphics;
   gg.CompositingQuality = CompositingQuality.HighQuality;
   gg.DrawImageUnscaled(m_Bitmap, 0, 0);
   //g.Dispose();
  }

  public Bitmap DrawClock()
  {
   return this.DrawClock(this.ClientRectangle);
  }

  private void SevenSegmentClock_Resize(object sender, System.EventArgs e)
  {
   Init();
   this.Refresh();
  }

  private void InitializeComponent()
  {
   //
   // SevenSegmentClock
   //
   this.Name = "SevenSegmentClock";
   this.Size = new System.Drawing.Size(448, 64);
   this.Resize += new System.EventHandler(this.SevenSegmentClock_Resize);
  }

  int _clockStringWidth;
  int _clockStringHeight;
  public int ClockStringWidth
  {
   get
   {
    return _clockStringWidth;
   }
  }
  
  public int ClockStringHeight
  {
   get
   {
    return _clockStringHeight;
   }
  }

//绘制时钟
  public Bitmap DrawClock(Rectangle destRect)
  {
   m_Bitmap = new Bitmap(destRect.Width, destRect.Height);
   //m_Bitmap = new Bitmap(destRect.X + this.Width, destRect.Y + this.Height);
   Graphics grfx = Graphics.FromImage(m_Bitmap);
//设置绘图面板的绘制质量等
   grfx.CompositingQuality = CompositingQuality.HighQuality;
   grfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
   grfx.SmoothingMode = SmoothingMode.HighQuality;

   SevenSegmentDisplay ssd = new SevenSegmentDisplay(grfx);
   ssd.IsDrawShadow = this._isDrawShadow;
   GraphicsState gs = grfx.Save();
   grfx.TranslateTransform(destRect.X, destRect.Y);
   string strTime = string.Empty;
   if(this._clockStyle == SevenSegmentClockStyle.TimeOnly)
   {
    strTime = _dateTime.ToString("T", DateTimeFormatInfo.InvariantInfo);
   }
   else if(this._clockStyle == SevenSegmentClockStyle.DateOnly)
   {
//设置日期格式
    strTime = _dateTime.ToString("yyyy-MM-dd", DateTimeFormatInfo.InvariantInfo);
   }
   else
   {
    strTime = _dateTime.ToString("yyyy-MM-dd", DateTimeFormatInfo.InvariantInfo) + " " + _dateTime.ToString("T", DateTimeFormatInfo.InvariantInfo);
   }

   SizeF  sizef   = ssd.MeasureString(strTime, Font);
   float  fScale  = Math.Min(destRect.Width  / sizef.Width, destRect.Height / sizef.Height);
   Font   font    = new Font(Font.FontFamily, fScale * Font.SizeInPoints);

   sizef = ssd.MeasureString(strTime, font);
   _clockStringWidth = (int)sizef.Width;
   _clockStringHeight = (int)sizef.Height;

   ssd.DrawString(strTime, font, new SolidBrush(this._clockColor),
    (destRect.Width  - sizef.Width) / 2,
    (destRect.Height - sizef.Height) / 2);
   grfx.Restore(gs);
   return m_Bitmap;
  }
 }
}

//--------------------------(如转载,请保留版权信息)-------------------------//
//   SevenSegmentDisplay.cs 2001 by Charles Petzold                        //
//------------------------改编:朱继山 a3news(AT)hotmail.com  -----------//
using System;
using System.Drawing;
using System.Windows.Forms;

namespace BrawDraw.Com.PhotoFrame.Net.PublicFunctions.Clock
{
//字符绘制的算法
 class SevenSegmentDisplay
 {
  Graphics grfx;
  Brush _brush = Brushes.Black;
  bool _isDrawShadow = true;
  Color _shadowColor = Color.FromArgb(60, Color.White);
  Brush _shadowBrush = null;
  // Indicates what segments are illuminated for all 10 digits

  static byte[,] bySegment = {
         {1, 1, 1, 0, 1, 1, 1},       // 0
         {0, 0, 1, 0, 0, 1, 0},       // 1
         {1, 0, 1, 1, 1, 0, 1},       // 2
         {1, 0, 1, 1, 0, 1, 1},       // 3
         {0, 1, 1, 1, 0, 1, 0},       // 4
         {1, 1, 0, 1, 0, 1, 1},       // 5
         {1, 1, 0, 1, 1, 1, 1},       // 6
         {1, 0, 1, 0, 0, 1, 0},       // 7
         {1, 1, 1, 1, 1, 1, 1},       // 8
         {1, 1, 1, 1, 0, 1, 1}        // 9
           };
  // Points that define each of the seven segments
  readonly Point[][] apt = new Point[7][];

  public bool IsDrawShadow
  {
   get { return this._isDrawShadow; }
   set { this._isDrawShadow = value; }
  }

  public SevenSegmentDisplay(Graphics grfx)
  {
   this.grfx = grfx;
   // Initialize jagged Point array.
   apt[0] = new Point[] {
          new Point( 3,  2), new Point(39,  2),
          new Point(31, 10), new Point(11, 10)
         };

   apt[1] = new Point[] {
          new Point( 2,  3), new Point(10, 11),
          new Point(10, 31), new Point( 2, 35)
         };

   apt[2] = new Point[] {
          new Point(40,  3), new Point(40, 35),
          new Point(32, 31), new Point(32, 11)
         };

   apt[3] = new Point[] {
          new Point( 3, 36), new Point(11, 32),
          new Point(31, 32), new Point(39, 36),
          new Point(31, 40), new Point(11, 40)
         };

   apt[4] = new Point[] {
          new Point( 2, 37), new Point(10, 41),
          new Point(10, 61), new Point( 2, 69)
         };

   apt[5] = new Point[] {
          new Point(40, 37), new Point(40, 69),
          new Point(32, 61), new Point(32, 41)
         };

   apt[6] = new Point[] {
          new Point(11, 62), new Point(31, 62),
          new Point(39, 70), new Point( 3, 70)
         };
  }

  public SizeF MeasureString(string str, Font font)
  {
   SizeF sizef = new SizeF(0, grfx.DpiX * font.SizeInPoints / 72);

   for (int i = 0; i < str.Length; i++)
   {
    if (Char.IsDigit(str[i]))
    {
     sizef.Width += 42 * grfx.DpiX * font.SizeInPoints / 72 / 72;
    }
    else if (str[i] == '-')
    {
     sizef.Width += 42 * grfx.DpiX * font.SizeInPoints / 72 / 72;
    }
    else if (str[i] == ':')
    {
     sizef.Width += 20 * grfx.DpiX * font.SizeInPoints / 72 / 72;
    }
    else if (str[i] == ' ')
    {
     sizef.Width += 36 * grfx.DpiX * font.SizeInPoints / 72 / 72;
    }
   }
   return sizef;
  }

  public void DrawString(string str, Font font, Brush brush, float x, float y)
  {
   this._brush = brush;
   this._shadowBrush = new SolidBrush(Color.FromArgb(40, ((SolidBrush)this._brush).Color));

   for (int i = 0; i < str.Length; i++)
   {
    if (Char.IsDigit(str[i]))
    {
     x = Number(str[i] - '0', font, brush, x, y);
    }
    else if (str[i] == '-')
    {
     x = MinusSign(font, brush, x, y);
    }
    else if (str[i] == ':')
    {
     x = Colon(font, brush, x, y);
    }
    else if (str[i] == ' ')
    {
     x = DrawSpace(font, brush, x, y);
    }
   }
  }

  private float Number(int num, Font font, Brush brush, float x, float y)
  {
   for (int i = 0; i < apt.Length; i++)
   {
    if(_isDrawShadow)
    {
     Fill(apt[i], font, _shadowBrush, x, y);
    }
    if (bySegment[num, i] == 1)
    {
     Fill(apt[i], font, brush, x, y);
    }
   }
   return x + 42 * grfx.DpiX * font.SizeInPoints / 72 / 72;
  }

  private float MinusSign(Font font, Brush brush, float x, float y)
  {
   Fill(apt[3], font, brush, x, y);
   return x + 42 * grfx.DpiX * font.SizeInPoints / 72 / 72;
  }

  private float DrawSpace(Font font, Brush brush, float x, float y)
  {
   return x + 36 * grfx.DpiX * font.SizeInPoints / 72 / 72;
  }

  private float Colon(Font font, Brush brush, float x, float y)
  {
   Point[][] apt = new Point[2][];

   apt[0] = new Point[] {
          new Point( 4, 12), new Point( 16, 12),
          new Point(16, 24), new Point( 4, 24)
         };

   apt[1] = new Point[] {
          new Point( 4, 50), new Point( 16, 50),
          new Point(16, 62), new Point( 4, 62)
         };

   for (int i = 0; i < apt.Length; i++)
   {
    Fill(apt[i], font, brush, x, y);
   }

   return x + 20 * grfx.DpiX * font.SizeInPoints / 72 / 72;
  }

  private void Fill(Point[] apt, Font font, Brush brush, float x, float y)
  {
   PointF[] aptf = new PointF[apt.Length];

   for (int i = 0; i < apt.Length; i++)
   {
    aptf[i].X = x + apt[i].X * grfx.DpiX * font.SizeInPoints / 72 / 72;
    aptf[i].Y = y + apt[i].Y * grfx.DpiY * font.SizeInPoints / 72 / 72;
   }

   grfx.FillPolygon(brush, aptf);
  }
 }
}