GDI+自定义时钟控件

说明:模拟带表盘的时钟

 

  1 using System;
  2 using System.Windows.Forms;
  3 using System.Drawing;
  4 using System.Drawing.Drawing2D;
  5 using System.Globalization;
  6 
  7 
  8 namespace BugQiang.Clocks {
  9     public class Clock : UserControl {
 10 
 11         Timer _timer;
 12 
 13         Graphics _grahpics;
 14 
 15         /// <summary>
 16         /// 坐标原点X
 17         /// </summary>
 18         float _centerX;
 19 
 20         /// <summary>
 21         /// 坐标原点Y
 22         /// </summary>
 23         float _centerY;
 24 
 25         /// <summary>
 26         /// 外圆的外接矩阵
 27         /// </summary>
 28         Rectangle _outerEllipse;
 29 
 30         /// <summary>
 31         /// 内圆的外接矩阵
 32         /// </summary>
 33         Rectangle _innerEllipse;
 34 
 35         /// <summary>
 36         /// 内圆半径
 37         /// </summary>
 38         float _innerEllipseRadius;
 39 
 40         //时分秒针的长度
 41         float _hourLength;
 42         float _minuteLength;
 43         float _secondLength;
 44 
 45         //外圆以及内圆与控件边界的距离
 46         int _outerSpan = 2;
 47         int _innerSpan = 5;
 48 
 49         /// <summary>
 50         /// 刻度长度
 51         /// </summary>
 52         float _scaleLength;
 53 
 54         Pen _outerEllipsePen;
 55         SolidBrush _innerEllipseBrush;
 56 
 57         Pen _bigScalePen;
 58         Pen _littleScalePen;
 59 
 60         SolidBrush _scaleValueBrush;
 61 
 62         Pen _hourPen;
 63         Pen _minutePen;
 64         Pen _secondPen;
 65 
 66         /// <summary>
 67         /// Hour的角度
 68         /// </summary>
 69         /// <remarks>平面直角坐标系正Y轴方向为参考</remarks>
 70         public float HourAngle {
 71             get {
 72                 return (DateTime.Now.Hour
 73                         + DateTime.Now.Minute / 60.0F
 74                         + DateTime.Now.Second / 3600.0F
 75                         + DateTime.Now.Millisecond / 3600000.0F) * 30F;
 76             }
 77         }
 78 
 79         /// <summary>
 80         /// Minute的角度
 81         /// </summary>
 82         /// <remarks>平面直角坐标系正Y轴方向为参考</remarks>
 83         public float MinuteAngle {
 84             get {
 85                 return (DateTime.Now.Minute
 86                         + DateTime.Now.Second / 60.0F
 87                         + DateTime.Now.Millisecond / 60000.0F) * 6F;
 88             }
 89         }
 90 
 91         /// <summary>
 92         /// Second的角度
 93         /// </summary>
 94         /// <remarks>平面直角坐标系正Y轴方向为参考</remarks>
 95         public float SecondAngle {
 96             get { return (DateTime.Now.Second + DateTime.Now.Millisecond / 1000.0F) * 6F; }
 97         }
 98 
 99         public Clock() {
100             InitializeComponent();
101             Initialize();
102             Initialize2();
103         }
104 
105         protected virtual void Initialize() {
106             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
107             this.SetStyle(ControlStyles.DoubleBuffer, true);
108             this.SetStyle(ControlStyles.ResizeRedraw, true);
109             this.SetStyle(ControlStyles.Selectable, true);
110             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
111             this.SetStyle(ControlStyles.UserPaint, true);
112             _timer = new Timer();
113             _timer.Enabled = true; //激活计时器
114             _timer.Interval = 50; //秒针每0.05秒刷新一次
115             _timer.Tick += delegate { this.Invalidate(); };
116             this.Resize += delegate {
117                 Width = Height;
118                 Initialize2();
119             };
120 
121             _outerEllipsePen = new Pen(Color.Black, 3);
122             _innerEllipseBrush = new SolidBrush(Color.Gray);
123 
124             _bigScalePen = new Pen(Color.Black, 4);
125             _littleScalePen = new Pen(Color.Black, 1);
126 
127             _scaleValueBrush = new SolidBrush(Color.White);
128 
129             _hourPen = new Pen(Color.White, 2.5F);
130 
131             _minutePen = new Pen(Color.Wheat, 1.75F);
132 
133             _secondPen = new Pen(Color.WhiteSmoke, 0.75F);
134         }
135 
136         private void Initialize2() {
137             _centerX = Width / 2;
138             _centerY = Height / 2;
139 
140             _outerEllipse = new Rectangle(_outerSpan, _outerSpan, Width - _outerSpan * 2, Height - _outerSpan * 2);
141             _innerEllipse = new Rectangle(_innerSpan, _innerSpan, Width - _innerSpan * 2, Height - _innerSpan * 2);
142 
143             _innerEllipseRadius = Width / 2 - _innerSpan;
144 
145             _hourLength = _innerEllipseRadius * 0.50F;
146             _minuteLength = _innerEllipseRadius * 0.75F;
147             _secondLength = _innerEllipseRadius * 0.90F;
148 
149             _scaleLength = 10;
150 
151         }
152 
153         protected override void OnPaint(PaintEventArgs e) {
154             base.OnPaint(e);
155             _grahpics = e.Graphics;
156             _grahpics.SmoothingMode = SmoothingMode.HighQuality;
157 
158             ////绘外圆以及内圆
159             _grahpics.DrawEllipse(_outerEllipsePen, _outerEllipse);
160             _grahpics.FillEllipse(_innerEllipseBrush, _innerEllipse);
161 
162             ////绘小刻度
163             ResetTransformCenter();165                 _grahpics.FillEllipse(new SolidBrush(Color.White), -5, -5, 10, 10); //绘中心圆点164             
          for (int i = 0; i < 60; i++) {
166 _grahpics.DrawLine(_littleScalePen, _innerEllipseRadius - _scaleLength, 0, _innerEllipseRadius, 0); 167 _grahpics.RotateTransform(6); 168 } 169 170 ////绘大刻度 171 ResetTransformCenter(); 172 for (int i = 0; i < 12; i++) { 173 _grahpics.DrawLine(_bigScalePen, _innerEllipseRadius - _scaleLength, 0, _innerEllipseRadius, 0); 174 _grahpics.RotateTransform(30); 175 } 176 177 ////绘刻度值 178 float x = 0F; 179 float y = 0F; 180 ResetTransformCenter(_centerX - 10, y + _innerEllipseRadius / 5F); 181 _grahpics.DrawString("12", 182 new Font("Times New Roman", 14, GraphicsUnit.Pixel), 183 _scaleValueBrush, 184 new PointF(x, 0)); 185 for (int i = 1; i < 6; i++) { 186 x = (float)(_innerEllipseRadius * Math.Sin(Math.PI * i / 6)); 187 y = (float)(_innerEllipseRadius * (1 - Math.Cos(Math.PI * i / 6))); 188 ResetTransformCenter(_centerX, y); 189 if (i == 3) { 190 _grahpics.DrawString(i.ToString(CultureInfo.InvariantCulture), 191 new Font("Times New Roman", 14, GraphicsUnit.Pixel), 192 _scaleValueBrush, 193 new PointF(x - 25, 0)); 194 _grahpics.DrawString((12 - i).ToString(CultureInfo.InvariantCulture), 195 new Font("Times New Roman", 14, GraphicsUnit.Pixel), 196 _scaleValueBrush, 197 new PointF(-x + 15, 0)); 198 } else if (i < 3) { 199 _grahpics.DrawString(i.ToString(CultureInfo.InvariantCulture), 200 new Font("Times New Roman", 14, GraphicsUnit.Pixel), 201 _scaleValueBrush, 202 new PointF(x - 25, _innerEllipseRadius / 6F)); 203 _grahpics.DrawString((12 - i).ToString(CultureInfo.InvariantCulture), 204 new Font("Times New Roman", 14, GraphicsUnit.Pixel), 205 _scaleValueBrush, 206 new PointF(-x + _innerEllipseRadius / 8F, _innerEllipseRadius / 6F)); 207 } else if (i > 3) { 208 _grahpics.DrawString(i.ToString(CultureInfo.InvariantCulture), 209 new Font("Times New Roman", 14, GraphicsUnit.Pixel), 210 _scaleValueBrush, 211 new PointF(x - 25, -_innerEllipseRadius / 6F)); 212 _grahpics.DrawString((12 - i).ToString(CultureInfo.InvariantCulture), 213 new Font("Times New Roman", 14, GraphicsUnit.Pixel), 214 _scaleValueBrush, 215 new PointF(-x + _innerEllipseRadius / 8F, -_innerEllipseRadius / 6F)); 216 } 217 } 218 x = 0F; 219 y = _innerEllipseRadius * 2; 220 ResetTransformCenter(_centerX - 5, y - _innerEllipseRadius / 5F); 221 _grahpics.DrawString("6", 222 new Font("Times New Roman", 14, GraphicsUnit.Pixel), 223 _scaleValueBrush, 224 new PointF(x, 0)); 225 226 ////绘秒针 227 ResetTransformCenter(); 228 _grahpics.RotateTransform(-90); 229 _grahpics.RotateTransform(SecondAngle); 230 _grahpics.DrawLine(_secondPen, -20, 0, _secondLength, 0); 231 232 ////绘分针 233 ResetTransformCenter(); 234 _grahpics.RotateTransform(-90); 235 _grahpics.RotateTransform(MinuteAngle); 236 _grahpics.DrawLine(_minutePen, 0, 0, _minuteLength, 0); 237 238 ////绘时针 239 ResetTransformCenter(); 240 _grahpics.RotateTransform(-90); 241 _grahpics.RotateTransform(HourAngle); 242 _grahpics.DrawLine(_hourPen, 0, 0, _hourLength, 0); 243 } 244 245 /// <summary> 246 /// 重置坐标原点(_centerX,_centerY) 247 /// </summary> 248 private void ResetTransformCenter() { 249 ResetTransformCenter(_centerX, _centerY); 250 } 251 252 /// <summary> 253 /// 重置坐标原点(centerX,centerY) 254 /// </summary> 255 /// <param name="centerX">坐标原点X</param> 256 /// <param name="centerY">坐标原点Y</param> 257 /// <remarks>坐标(centerX,centerY)以控件的右上角为参考点</remarks> 258 private void ResetTransformCenter(float centerX, float centerY) { 259 _grahpics.ResetTransform(); 260 _grahpics.TranslateTransform(centerX, centerY); 261 } 262 263 264 /// <summary> 265 /// 必需的设计器变量。 266 /// </summary> 267 private System.ComponentModel.IContainer components = null; 268 269 /// <summary> 270 /// 清理所有正在使用的资源。 271 /// </summary> 272 /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> 273 protected override void Dispose(bool disposing) { 274 if (disposing && (components != null)) { 275 components.Dispose(); 276 } 277 278 if (disposing && _outerEllipsePen != null) 279 _outerEllipsePen.Dispose(); 280 if (disposing && _innerEllipseBrush != null) 281 _innerEllipseBrush.Dispose(); 282 283 if (disposing && _bigScalePen != null) 284 _bigScalePen.Dispose(); 285 if (disposing && _littleScalePen != null) 286 _littleScalePen.Dispose(); 287 288 if (disposing && _scaleValueBrush != null) 289 _scaleValueBrush.Dispose(); 290 291 if (disposing && _hourPen != null) 292 _hourPen.Dispose(); 293 if (disposing && _minutePen != null) 294 _minutePen.Dispose(); 295 if (disposing && _secondPen != null) 296 _secondPen.Dispose(); 297 298 base.Dispose(disposing); 299 } 300 301 #region 组件设计器生成的代码 302 303 /// <summary> 304 /// 设计器支持所需的方法 - 不要 305 /// 使用代码编辑器修改此方法的内容。 306 /// </summary> 307 private void InitializeComponent() { 308 this.SuspendLayout(); 309 // 310 // Clock 311 // 312 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 313 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 314 this.Name = "Clock"; 315 this.Size = new System.Drawing.Size(227, 223); 316 this.ResumeLayout(false); 317 } 318 319 #endregion 320 } 321 }

 

PS:.NET坐标系,以画布的左上角为原点,分别取平面直角坐标系的正X以及负Y(.NET作为正Y).

posted @ 2013-07-07 00:43  小麦粉  阅读(1252)  评论(1编辑  收藏  举报