Csharp/CSharp Tutorial/2D/Clock

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

our clock

<source lang="csharp">/* Quote from Programming .NET Windows Applications By Jesse Liberty, Dan Hurwitz First Edition October 2003 Pages: 1246 (More details)

  • /


using System; using System.Collections; using System.ruponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Timers; using System.Windows.Forms; public class Form1 : System.Windows.Forms.Form {

 private System.ruponentModel.IContainer components;
 private int FaceRadius = 450;    // size of the clock face
 private bool b24Hours = false;    // 24 hour clock face?
 private System.Windows.Forms.Button btnClockFormat;
 private System.Windows.Forms.Timer timer1;        // center of the clock
 private DateTime currentTime;    // used in more than one method
 public Form1()
 {
   // Required for Windows Form Designer support
   InitializeComponent();
   // use the user"s choice of colors
   BackColor = SystemColors.Window;
   ForeColor = SystemColors.WindowText;
   timer1.Interval = 500;
   timer1.Enabled = true;
 }
 protected override void OnPaint ( PaintEventArgs e )
 {
   Graphics g = e.Graphics;
   SetScale(g);
   DrawFace(g);
   DrawTime(g,true);  // force an update
 }


 #region Windows Form Designer generated code
 protected override void Dispose( bool disposing )
 {
   if( disposing )
   {
     if (components != null) 
     {
       components.Dispose();
     }
   }
   base.Dispose( disposing );
 }
 
 /// <summary>
 /// Required method for Designer support - do not modify
 /// the contents of this method with the code editor.
 /// </summary>
 private void InitializeComponent()
 {
   this.ruponents = new System.ruponentModel.Container();
   this.btnClockFormat = new System.Windows.Forms.Button();
   this.timer1 = new System.Windows.Forms.Timer(this.ruponents);
   this.SuspendLayout();
   // 
   // btnClockFormat
   // 
   this.btnClockFormat.Location = new System.Drawing.Point(8, 8);
   this.btnClockFormat.Name = "btnClockFormat";
   this.btnClockFormat.TabIndex = 1;
   this.btnClockFormat.Text = "24 Hours";
   this.btnClockFormat.Click += new System.EventHandler(this.btnClockFormat_Click);
   // 
   // timer1
   // 
   this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
   // 
   // Form1
   // 
   this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
   this.ClientSize = new System.Drawing.Size(292, 266);
   this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                   this.btnClockFormat});
   this.Name = "Form1";
   this.Text = "Clock2CS";
   this.ResumeLayout(false);
 }
 #endregion
 [STAThread]
 static void Main() 
 {
   Application.Run(new Form1());
 }
 private void SetScale(Graphics g)
 {
   // if the form is too small, do nothing
   if ( Width == 0 || Height == 0 )
     return;
   // set the origin at the center
   g.TranslateTransform(Width/2, Height/2);
   // set inches to the minimum of the width 
   // or height dividedby the dots per inch  
   float inches = Math.Min(Width / g.DpiX, Height / g.DpiX);
   // set the scale to a grid of 2000 by 2000 units
   g.ScaleTransform(
     inches * g.DpiX / 2000, inches * g.DpiY / 2000);
 }
 private void DrawFace(Graphics g)
 {
   // numbers are in forecolor except flash number in green
   // as the seconds go by.
   Brush brush = new SolidBrush(ForeColor);
   Font font = new Font("Arial", 40);
   float x, y;
   // new code
   int numHours = b24Hours ? 24 : 12;
   int deg = 360 / numHours;
   
   // for each of the hours on the clock face
   for (int i = 1; i <= numHours; i++)
   {
     // i = hour  30 degrees = offset per hour  
     // +90 to make 12 straight up
     x = GetCos(i*deg + 90) * FaceRadius;
     y = GetSin(i*deg + 90) * FaceRadius;
     StringFormat format = new StringFormat();
     format.Alignment = StringAlignment.Center;
     format.LineAlignment = StringAlignment.Center;
     g.DrawString(
       i.ToString(), font, brush, -x, -y,format);
   
   }  // end for loop
 }    // end drawFace
 private void DrawTime(Graphics g, bool forceDraw)
 {
   //  length of the hands
   float hourLength = FaceRadius * 0.5f;
   float minuteLength = FaceRadius * 0.7f;
   float secondLength = FaceRadius * 0.9f;
   // set to back color to erase old hands first
   Pen hourPen = new Pen(BackColor);
   Pen minutePen = new Pen(BackColor);
   Pen secondPen = new Pen(BackColor);
   // set the arrow heads
   hourPen.EndCap = LineCap.ArrowAnchor;
   minutePen.EndCap = LineCap.ArrowAnchor;
   // hour hand is thicker
   hourPen.Width = 30;
   minutePen.Width = 20;
   // second hand 
   Brush secondBrush = new SolidBrush(BackColor);
   const int EllipseSize = 50;
   GraphicsState state;  // to to protect and to serve
   // 1 - delete the old time
   // delete the old second hand
   // figure out how far around to rotate to draw the second hand
   // save the current state, rotate, draw and then restore the state
   float rotation = GetSecondRotation();
   state = g.Save();
   g.RotateTransform(rotation);
   g.FillEllipse(
     secondBrush,
     -(EllipseSize/2),
     -secondLength,
     EllipseSize,
     EllipseSize);
   g.Restore(state);
   DateTime newTime = DateTime.Now;
   bool newMin = false;  // has the minute changed?
   // if the minute has changed, set the flag
   if ( newTime.Minute != currentTime.Minute )
     newMin = true;
   // if the minute has changed or you must draw anyway then you 
   // must first delete the old minute and hour hand
   if ( newMin  || forceDraw )
   {
     // figure out how far around to rotate to draw the minute hand
     // save the current state, rotate, draw and then restore the state
     rotation = GetMinuteRotation();
     state = g.Save();
     g.RotateTransform(rotation);
     g.DrawLine(minutePen,0,0,0,-minuteLength);
     g.Restore(state);
     // figure out how far around to rotate to draw the hour hand
     // save the current state, rotate, draw and then restore the state
     rotation = GetHourRotation();
     state = g.Save();
     g.RotateTransform(rotation);
     g.DrawLine(hourPen,0,0,0,-hourLength);
     g.Restore(state);
   }
   // step 2 - draw the new time
   currentTime = newTime;
   hourPen.Color = Color.Red;
   minutePen.Color = Color.Blue;
   secondPen.Color = Color.Green;
   secondBrush = new SolidBrush(Color.Green);
   // draw the new second hand
   // figure out how far around to rotate to draw the second hand
   // save the current state, rotate, draw and then restore the state
   state = g.Save();
   rotation = GetSecondRotation();
   g.RotateTransform(rotation);
   g.FillEllipse(
     secondBrush,
     -(EllipseSize/2),
     -secondLength,
     EllipseSize,
     EllipseSize);
   g.Restore(state);
   // if the minute has changed or you must draw anyway then you 
   // must draw the new minute and hour hand
   if ( newMin || forceDraw )
   {
     // figure out how far around to rotate to draw the minute hand
     // save the current state, rotate, draw and then restore the state
     state = g.Save();
     rotation = GetMinuteRotation();
     g.RotateTransform(rotation);
     g.DrawLine(minutePen,0,0,0,-minuteLength);
     g.Restore(state);
     // figure out how far around to rotate to draw the hour hand
     // save the current state, rotate, draw and then restore the state
     state = g.Save();
     rotation = GetHourRotation();
     g.RotateTransform(rotation);
     g.DrawLine(hourPen,0,0,0,-hourLength);
     g.Restore(state);
   }
 }
 // determine the rotation to draw the hour hand
 private float GetHourRotation()
 {
   // degrees depend on 24 vs. 12 hour clock
   float deg = b24Hours ? 15 : 30;
   float numHours = b24Hours ? 24 : 12;
   return( 360f * currentTime.Hour / numHours +
     deg * currentTime.Minute / 60f);
 }
 private float GetMinuteRotation()
 {
   return( 360f * currentTime.Minute / 60f ); 
 }
 private float GetSecondRotation()
 {
   return(360f * currentTime.Second / 60f);
 }
 private static float GetSin(float degAngle)
 {
   return (float) Math.Sin(Math.PI * degAngle / 180f);
 }
 private static float GetCos(float degAngle)
 {
   return (float) Math.Cos(Math.PI * degAngle / 180f);
 }
 private void btnClockFormat_Click(object sender, System.EventArgs e)
 {
   btnClockFormat.Text = b24Hours ? "24 Hour" : "12 Hour";
   b24Hours = ! b24Hours;
   this.Invalidate();
 }
 private void timer1_Tick(object sender, System.EventArgs e)
 {
   this.Invalidate();
 
 }

}</source>

Clock animation

<source lang="csharp">/* Quote from Programming .NET Windows Applications By Jesse Liberty, Dan Hurwitz First Edition October 2003 Pages: 1246 (More details)

  • /

using System; using System.Collections; using System.ruponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Timers; using System.Windows.Forms;

namespace Clock3CS {

 // Rename the class
 public class ClockFace : System.Windows.Forms.Form
 {
   // Required designer variable.
   private System.ruponentModel.Container components = null;
 
   private int FaceRadius = 450;    // size of the clock face
   private bool b24Hours = false;    // 24 hour clock face?
   private System.Windows.Forms.Button btnClockFormat;    
   private DateTime currentTime;    // used in more than one method
   // new
   private int xCenter;        // center of the clock
   private int yCenter;
   private static int DateRadius = 600; // outer circumference for date
   private static int Offset = 0;    // for moving the text 
   Font font = new Font("Arial", 40);  // use the same font throughout
   private StringDraw sdToday;      // the text to animate
   public ClockFace()
   {
     // Required for Windows Form Designer support
     InitializeComponent();
     // use the user"s choice of colors
     BackColor = SystemColors.Window;
     ForeColor = SystemColors.WindowText;
   
     // *** begin new
     string today = System.DateTime.Now.ToLongDateString();
     today = " " + today.Replace(",","");
     
     // create a new stringdraw object with today"s date
     sdToday = new StringDraw(today,this);
     currentTime = DateTime.Now;
     // set the current center based on the
     // client area
     xCenter = Width / 2;
     yCenter = Height / 2;
     // *** end new
     // update the clock by timer
     System.Timers.Timer timer = new System.Timers.Timer();
     timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimer);
     timer.Interval = 20;  // shorter interval - more movement
     timer.Enabled = true;
   }
   protected override void OnPaint ( PaintEventArgs e )
   {
     base.OnPaint(e);
     Graphics g = e.Graphics;
     SetScale(g);
     DrawFace(g);
     DrawTime(g,true);  // force an update
   }
   // every time the timer event fires, update the clock
   public void OnTimer(Object source, ElapsedEventArgs e)
   {
     Graphics g = this.CreateGraphics();
     SetScale(g);
     DrawFace(g);
     DrawTime(g,false);
     DrawDate(g);
     g.Dispose();    
     
   }
   #region Windows Form Designer generated code
   protected override void Dispose( bool disposing )
   {
     if( disposing )
     {
       if (components != null) 
       {
         components.Dispose();
       }
     }
     base.Dispose( disposing );
   }
   
   /// <summary>
   /// Required method for Designer support - do not modify
   /// the contents of this method with the code editor.
   /// </summary>
   private void InitializeComponent()
   {
     this.btnClockFormat = new System.Windows.Forms.Button();
     this.SuspendLayout();
     // 
     // btnClockFormat
     // 
     this.btnClockFormat.Location = new System.Drawing.Point(8, 8);
     this.btnClockFormat.Name = "btnClockFormat";
     this.btnClockFormat.TabIndex = 1;
     this.btnClockFormat.Text = "24 Hours";
     this.btnClockFormat.Click += new System.EventHandler(this.btnClockFormat_Click);
     // 
     // ClockFace
     // 
     this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
     this.ClientSize = new System.Drawing.Size(292, 266);
     this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                     this.btnClockFormat});
     this.Name = "ClockFace";
     this.Text = "Clock3CS";
     this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ClockFace_MouseDown);
     this.ResumeLayout(false);
   }
   #endregion
   [STAThread]
   static void Main() 
   {
     Application.Run(new ClockFace());
   }
   private void SetScale(Graphics g)
   {
     // if the form is too small, do nothing
     if ( Width == 0 || Height == 0 )
       return;
     // set the origin at the center
     g.TranslateTransform(xCenter, yCenter);  // use the members vars
     // set inches to the minimum of the width 
     // or height dividedby the dots per inch  
     float inches = Math.Min(Width / g.DpiX, Height / g.DpiX);
     // set the scale to a grid of 2000 by 2000 units
     g.ScaleTransform(
       inches * g.DpiX / 2000, inches * g.DpiY / 2000);
   }
   private void DrawFace(Graphics g)
   {
     // numbers are in forecolor except flash number in green
     // as the seconds go by.
     Brush brush = new SolidBrush(ForeColor);
     float x, y;
     // new code
     int numHours = b24Hours ? 24 : 12;
     int deg = 360 / numHours;
     
     // for each of the hours on the clock face
     for (int i = 1; i <= numHours; i++)
     {
       // i = hour  30 degrees = offset per hour  
       // +90 to make 12 straight up
       x = GetCos(i*deg + 90) * FaceRadius;
       y = GetSin(i*deg + 90) * FaceRadius;
       StringFormat format = new StringFormat();
       format.Alignment = StringAlignment.Center;
       format.LineAlignment = StringAlignment.Center;
       g.DrawString(
         i.ToString(), font, brush, -x, -y,format);
     
     }  // end for loop
   }    // end drawFace
   private void DrawTime(Graphics g, bool forceDraw)
   {
     //  length of the hands
     float hourLength = FaceRadius * 0.5f;
     float minuteLength = FaceRadius * 0.7f;
     float secondLength = FaceRadius * 0.9f;
     // set to back color to erase old hands first
     Pen hourPen = new Pen(BackColor);
     Pen minutePen = new Pen(BackColor);
     Pen secondPen = new Pen(BackColor);
     // set the arrow heads
     hourPen.EndCap = LineCap.ArrowAnchor;
     minutePen.EndCap = LineCap.ArrowAnchor;
     // hour hand is thicker
     hourPen.Width = 30;
     minutePen.Width = 20;
     // second hand 
     Brush secondBrush = new SolidBrush(BackColor);
     const int EllipseSize = 50;
     GraphicsState state;  // to to protect and to serve
     // 1 - delete the old time
     // delete the old second hand
     // figure out how far around to rotate to draw the second hand
     // save the current state, rotate, draw and then restore the state
     float rotation = GetSecondRotation();
     state = g.Save();
     g.RotateTransform(rotation);
     g.FillEllipse(
       secondBrush,
       -(EllipseSize/2),
       -secondLength,
       EllipseSize,
       EllipseSize);
     g.Restore(state);
     DateTime newTime = DateTime.Now;
     bool newMin = false;  // has the minute changed?
     // if the minute has changed, set the flag
     if ( newTime.Minute != currentTime.Minute )
       newMin = true;
     // if the minute has changed or you must draw anyway then you 
     // must first delete the old minute and hour hand
     if ( newMin  || forceDraw )
     {
       // figure out how far around to rotate to draw the minute hand
       // save the current state, rotate, draw and then restore the state
       rotation = GetMinuteRotation();
       state = g.Save();
       g.RotateTransform(rotation);
       g.DrawLine(minutePen,0,0,0,-minuteLength);
       g.Restore(state);
       // figure out how far around to rotate to draw the hour hand
       // save the current state, rotate, draw and then restore the state
       rotation = GetHourRotation();
       state = g.Save();
       g.RotateTransform(rotation);
       g.DrawLine(hourPen,0,0,0,-hourLength);
       g.Restore(state);
     }
     // step 2 - draw the new time
     currentTime = newTime;
     hourPen.Color = Color.Red;
     minutePen.Color = Color.Blue;
     secondPen.Color = Color.Green;
     secondBrush = new SolidBrush(Color.Green);
     // draw the new second hand
     // figure out how far around to rotate to draw the second hand
     // save the current state, rotate, draw and then restore the state
     state = g.Save();
     rotation = GetSecondRotation();
     g.RotateTransform(rotation);
     g.FillEllipse(
       secondBrush,
       -(EllipseSize/2),
       -secondLength,
       EllipseSize,
       EllipseSize);
     g.Restore(state);
     // if the minute has changed or you must draw anyway then you 
     // must draw the new minute and hour hand
     if ( newMin || forceDraw )
     {
       // figure out how far around to rotate to draw the minute hand
       // save the current state, rotate, draw and then restore the state
       state = g.Save();
       rotation = GetMinuteRotation();
       g.RotateTransform(rotation);
       g.DrawLine(minutePen,0,0,0,-minuteLength);
       g.Restore(state);
       // figure out how far around to rotate to draw the hour hand
       // save the current state, rotate, draw and then restore the state
       state = g.Save();
       rotation = GetHourRotation();
       g.RotateTransform(rotation);
       g.DrawLine(hourPen,0,0,0,-hourLength);
       g.Restore(state);
     }
   }
   // determine the rotation to draw the hour hand
   private float GetHourRotation()
   {
     // degrees depend on 24 vs. 12 hour clock
     float deg = b24Hours ? 15 : 30;
     float numHours = b24Hours ? 24 : 12;
     return( 360f * currentTime.Hour / numHours +
       deg * currentTime.Minute / 60f);
   }
   private float GetMinuteRotation()
   {
     return( 360f * currentTime.Minute / 60f ); 
   }
   private float GetSecondRotation()
   {
     return(360f * currentTime.Second / 60f);
   }
   private static float GetSin(float degAngle)
   {
     return (float) Math.Sin(Math.PI * degAngle / 180f);
   }
   private static float GetCos(float degAngle)
   {
     return (float) Math.Cos(Math.PI * degAngle / 180f);
   }
   private void btnClockFormat_Click(object sender, System.EventArgs e)
   {
     btnClockFormat.Text = b24Hours ? "24 Hour" : "12 Hour";
     b24Hours = ! b24Hours;
     this.Invalidate();
   }
   private void DrawDate(Graphics g)
   {
     Brush brush = new SolidBrush(ForeColor);
     sdToday.DrawString(g,brush);
   }
   private void ClockFace_MouseDown(
     object sender, System.Windows.Forms.MouseEventArgs e)
   {
     xCenter = e.X;
     yCenter = e.Y;
     this.Invalidate();
   
   }
   // each letter in the outer string knows how to draw itself
   private class LtrDraw
   {
     char myChar;    // the actual letter i draw
     float x;      // current x coordinate
     float y;      // current y coordinate
     float oldx;      // old x coordinate (to delete)
     float oldy;      // old y coordinate (to delete)
     
     // constructor
     public LtrDraw(char c)
     {
       myChar = c;
     }
     // property for X coordinate
     public float X
     {
       get { return x; }
       set { oldx = x; x = value; }
     }
     // property for Y coordinate
     public float Y
     {
       get { return y; }
       set { oldy = y; y = value; }
     }
     // get total width of the string
     public float GetWidth(Graphics g, Font font)
     {
       SizeF stringSize = g.MeasureString(myChar.ToString(),font);
       return stringSize.Width;
     }
     // get total height of the string
     public float GetHeight(Graphics g, Font font)
     {
       SizeF stringSize = g.MeasureString(myChar.ToString(),font);
       return stringSize.Height;
     }
     // get the font from the control and draw the current character
     // First delete the old and then draw the new
     public void DrawString(Graphics g, Brush brush, ClockFace cf)
     {
       Font font = cf.font;
       Brush blankBrush = new SolidBrush(cf.BackColor);
       g.DrawString(myChar.ToString(),font,blankBrush,oldx,oldy);
       g.DrawString(myChar.ToString(),font,brush,x,y);
     }
   }
   // holds an array of LtrDraw objects
   // and knows how to tell them to draw
   private class StringDraw
   {
     ArrayList theString = new ArrayList();
     LtrDraw l;
     ClockFace theControl;
     // constructor takes a string, populates the array
     // and stashes away the calling control (ClockFace)
     public StringDraw(string s, ClockFace theControl)
     {
       this.theControl = theControl;
       foreach (char c in s)
       {
         l = new LtrDraw(c);
         theString.Add(l);
       }
     }
     // divide the circle by the number of letters
     // and draw each letter in position
     public void DrawString(Graphics g, Brush brush)
     {
       int angle = 360 / theString.Count;
       int counter = 0;
       foreach (LtrDraw theLtr in theString)
       {
         // 1. To find the X coordinate, take the Cosine of the angle
         // and multiply by the radius.
         // 2. To compute the angle, start with the base angle 
         // (360 divided by the number of letters)
         // and multiply by letter position.
         // Thus if each letter is 10 degrees, and this is the third
         // letter, you get 30 degrees. Add 90 to start at 12 O"clock.
         // Each time through, subtract the clockFace offset to move 
         // the entire string around the clock on each timer call
         float newX = GetCos(angle  * counter + 90 - ClockFace.Offset) * ClockFace.DateRadius ;
         float newY = GetSin(angle * counter + 90 - ClockFace.Offset) * ClockFace.DateRadius ;
         theLtr.X = 
           newX - (theLtr.GetWidth(g,theControl.font) / 2);
         theLtr.Y = 
           newY - (theLtr.GetHeight(g,theControl.font) / 2);
         counter++;
         theLtr.DrawString(g,brush,theControl);
       }
       ClockFace.Offset += 1;  // rotate the entire string
     }
   }
 }  // end class

} // end namespace</source>