Csharp/C Sharp/Components/Clock
A Clock
<source lang="csharp"> /* Code revised from chapter 4
GDI+ Custom Controls with Visual C# 2005 By Iulian Serban, Dragos Brezoi, Tiberiu Radu, Adam Ward Language English Paperback 272 pages [191mm x 235mm] Release date July 2006 ISBN 1904811604 Sample chapter http://www.packtpub.ru/files/1604_CustomControls_SampleChapter.pdf
For More info on GDI+ Custom Control with Microsoft Visual C# book visit website www.packtpub.ru
- /
using System; using System.Collections.Generic; using System.ruponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace ClockTest00 {
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private System.ruponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.clock1 = new ClockTest00.Clock(); this.SuspendLayout(); // // clock1 // this.clock1.BackColor = System.Drawing.SystemColors.ControlLightLight; this.clock1.HourColor = System.Drawing.Color.Black; this.clock1.Location = new System.Drawing.Point(67, 49); this.clock1.MinuteColor = System.Drawing.Color.Black; this.clock1.Name = "clock1"; this.clock1.SecondColor = System.Drawing.Color.Black; this.clock1.Size = new System.Drawing.Size(150, 150); this.clock1.TabIndex = 0; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(292, 266); this.Controls.Add(this.clock1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } #endregion private Clock clock1;
[STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } public partial class Clock : UserControl { public Clock() { //Sets the rendering mode of the control to double buffer to stop flickering this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); InitializeComponent(); //Enables the timer so the clock refreshes every second timer.Enabled = true; MakeRound(); } private Color hourColor = Color.Black; private Color minuteColor = Color.Black; private Color secondColor = Color.Black; public Color HourColor { get { return hourColor; } set { if (hourColor != value) { hourColor = value; Invalidate(); } } } public Color MinuteColor { get { return minuteColor; } set { if (minuteColor != value) { minuteColor = value; Invalidate(); } } } public Color SecondColor { get { return secondColor; } set { if (secondColor != value) { secondColor = value; Invalidate(); } } }
protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); //Smooths out the appearance of the control e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; //The center of the control, that is used as center for the clock PointF center = new PointF(this.Width / 2, this.Height / 2); //The distace of the text from the center float textRadius = (Math.Min(Width, Height) - Font.Height) / 2; //The distance of the margin points from the center float outerRadius = Math.Min(Width, Height) / 2 - Font.Height; //The length of the hour line float hourRadius = outerRadius * 6 / 9; //The length of the minute line float minuteRadius = outerRadius * 7 / 9; //The length of the second line float secondRadius = outerRadius * 8 / 9; for (int i = 1; i <= 60; i++) { //Gets the angle of the outer dot float angle = GetAngle(i / 5f, 12); //Gets the location of the outer dot PointF dotPoint = GetPoint(center, outerRadius, angle); //Indicates the size of the point int pointSize = 2; //Is true when a large dot needs to be rendered if (i % 5 == 0) { //Sets the size of the point to make it bigger pointSize = 4; //The hour number string text = (i / 5).ToString(); SizeF sz = e.Graphics.MeasureString(text, Font); //The point where the text should be rendered PointF textPoint = GetPoint(center, textRadius, angle); //Offsets the text location so it is centered in that point. textPoint.X -= sz.Width / 2; textPoint.Y -= sz.Height / 2; //Draws the hour number e.Graphics.DrawString(text, Font, new SolidBrush(this.ForeColor), textPoint); } Pen pen = new Pen(new SolidBrush(this.ForeColor), 1); //Draws the outer dot of the clock e.Graphics.DrawEllipse(pen, dotPoint.X - pointSize / 2, dotPoint.Y - pointSize / 2, pointSize, pointSize); pen.Dispose(); } //Gets the system time DateTime dt = DateTime.Now; //Calculates the hour offset from the large outer dot float min = ((float)dt.Minute) / 60; //Calculates the angle of the hour line float hourAngle = GetAngle(dt.Hour + min, 12); //Calculates the angle of the minute line float minuteAngle = GetAngle(dt.Minute, 60); //Calculates the angle of the second line float secondAngle = GetAngle(dt.Second, 60); //Draws the clock lines DrawLine(e.Graphics, this.secondColor, 1, center, secondRadius, secondAngle); DrawLine(e.Graphics, this.minuteColor, 2, center, minuteRadius, minuteAngle); DrawLine(e.Graphics, this.hourColor, 3, center, hourRadius, hourAngle); e.Graphics.ResetTransform(); } private PointF GetPoint(PointF center, float radius, float angle) { //Calculates the X coordinate of the point float x = (float)Math.Cos(2 * Math.PI * angle / 360) * radius + center.X; //Calculates the Y coordinate of the point float y = -(float)Math.Sin(2 * Math.PI * angle / 360) * radius + center.Y; return new PointF(x, y); } private void DrawLine(Graphics g, Color color, int penWidth, PointF center, float radius, float angle) { //Calculates the end point of the line PointF endPoint = GetPoint(center, radius, angle); //Creates the pen used to render the line Pen pen = new Pen(new SolidBrush(color), penWidth); //Renders the line g.DrawLine(pen, center, endPoint); pen.Dispose(); } private void MakeRound() { GraphicsPath gp = new GraphicsPath(); float min = Math.Min(Width, Height); //Creates the ellipse shape gp.AddEllipse((Width - min) / 2, (Height - min) / 2, min, min); //Creates the ellipse region Region rgn = new Region(gp); //Sets the ellipse region to the control this.Region = rgn; } private float GetAngle(float clockValue, float divisions) { //Calculates the angle return 360 - (360 * (clockValue) / divisions) + 90; }
private void timer_Tick(object sender, EventArgs e) { Invalidate(); } private void Clock_SizeChanged(object sender, EventArgs e) { MakeRound(); Invalidate(); } private void Clock_Paint(object sender, PaintEventArgs e) { } private System.ruponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// <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.timer = new System.Windows.Forms.Timer(this.ruponents); this.SuspendLayout(); // // timer // this.timer.Interval = 1000; this.timer.Tick += new System.EventHandler(this.timer_Tick); // // Clock // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Name = "Clock"; this.Paint += new System.Windows.Forms.PaintEventHandler(this.Clock_Paint); this.SizeChanged += new System.EventHandler(this.Clock_SizeChanged); this.ResumeLayout(false); } #endregion private System.Windows.Forms.Timer timer; }
}
</source>