C#
時鐘控件的創建與使用
<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 162pt; HEIGHT: 173.25pt" type="#_x0000_t75"><imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image001.png" o:title="" croptop="14473f" cropbottom="16459f" cropleft="9926f" cropright="29999f"></imagedata></shape>
簡介:效果如圖。
本文假定讀者熟悉基本的
C#
編程過程,但對建立控件的過程不太了解,以一個時鐘控件為例,詳細描述了開發過程,希望對大家有所幫助。
1、
時間變換部分
-----
只需要比較簡單的數學知識
首先取得當前時間
int hour = dateTime.Hour % 12; //
將小時數(
24
基)轉換成
12
基的
int minute = dateTime.Minute;
int sec = dateTime.Second;
將這些數據轉換成相應的弧度(因為
sin
所)
float hourRadian = hour * 360/12 * PI/180;
float minRadian = minute * 360/60 * PI/180;
float secRadian = sec * 360/60 * PI/180;
根據弧度得出了時針的端點
float hourEndPointX = lengthofHourHand * System.Math.Sin(hourRadian)
float hourEndPointY = lengthofHourHand * System.Math.Cos(hourRadian)
則時針畫法為
Line(centerX, centerY, hourEndPointX, hourEndPointY)
分針、秒針以此類類推。
2、
詳細步驟
<shape id="_x0000_i1026" style="WIDTH: 219pt; HEIGHT: 150pt" type="#_x0000_t75"><imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image003.png" o:title="" croptop="15851f" cropbottom="20209f" cropleft="15178f" cropright="15732f"><font face="Times New Roman" size="3"></font></imagedata></shape>
首先創建一個工程命名為
AnalogClockControl.
選擇
Windows Control Library
為模板。
從工程中刪除
usercontrol1.cs
文件,并向其中新增加一個類。
<shape id="_x0000_i1027" style="WIDTH: 219pt; HEIGHT: 246.75pt" type="#_x0000_t75"><imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image005.png" o:title="" cropbottom="29412f" cropleft="39843f"><font size="3"></font></imagedata></shape>
向你的控件中拖入一個
timer
控件,將其
Interval
屬性設為
1000
(每
1000
毫秒發出一個
WM_TIMER
消息)。
下面開始編程
,
類的架構:
class AnalogClock : System.Windows.Forms.UserControl
{
const float PI=<chmetcnv unitname="F" sourcevalue="3.141592654" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">3.141592654F</chmetcnv>;
DateTime dateTime;
float fRadius;
float fCenterX;
float fCenterY;
float fCenterCircleRadius;
float fHourLength;
float fMinLength;
float fSecLength;
float fHourThickness;
float fMinThickness;
float fSecThickness;
bool bDraw5MinuteTicks=true;
bool bDraw1MinuteTicks=true;
float fTicksThickness=1;
Color hrColor=Color.DarkMagenta ;
Color minColor=Color.Green ;
Color secColor=Color.Red ;
Color circleColor=Color.Red;
Color ticksColor=Color.Black;
...
...
為了確??丶怀醮渭虞d及被改變大小時都能正常顯示時間,我們有必要在
Load
與
Resize
事件發生時予以響應。
程序如下:
private void AnalogClock_Load(object sender, System.EventArgs e)
{
dateTime=DateTime.Now;
this.AnalogClock_Resize(sender,e);
}
private void AnalogClock_Resize(object sender, System.EventArgs e)
{
this.Width = this.Height;
this.fRadius = this.Height/2;
this.fCenterX = this.ClientSize.Width/2;
this.fCenterY = this.ClientSize.Height/2;
this.fHourLength = (float)this.Height/3/<chmetcnv unitname="F" sourcevalue="1.65" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.65F</chmetcnv>;
this.fMinLength = (float)this.Height/3/<chmetcnv unitname="F" sourcevalue="1.2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.20F</chmetcnv>;
this.fSecLength = (float)this.Height/3/<chmetcnv unitname="F" sourcevalue="1.15" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.15F</chmetcnv>;
this.fHourThickness = (float)this.Height/100;
this.fMinThickness = (float)this.Height/150;
this.fSecThickness = (float)this.Height/200;
this.fCenterCircleRadius = this.Height/50;
this.Refresh();
}
為完成時鐘效果,程序應該每秒鐘刷新一次時、分、秒針的位置。雙擊
timer
控件,在其響應函數中加入如下代碼:
private void timer1_Tick(object sender, System.EventArgs e)
{
this.dateTime=DateTime.Now;
this.Refresh();
}
下面來寫一下兩個與圖形有關的函數,
DrawLine()
與
DrawPolygon(),
它們的作用是在窗體上畫出秒針與時分針。
代碼如下:
private void DrawLine(float fThickness, float fLength, Color color,
float fRadians, System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.DrawLine(new Pen( color, fThickness ),
fCenterX - (float)(fLength/9*System.Math.Sin(fRadians)),
fCenterY + (float)(fLength/9*System.Math.Cos(fRadians)),
fCenterX + (float)(fLength*System.Math.Sin(fRadians)),
fCenterY - (float)(fLength*System.Math.Cos(fRadians)));
}
private void DrawPolygon(float fThickness, float fLength, Color color,
float fRadians, System.Windows.Forms.PaintEventArgs e)
{
PointF A=new PointF( (float)(fCenterX+
fThickness*2*System.Math.Sin(fRadians+PI/2)),
(float)(fCenterY -
fThickness*2*System.Math.Cos(fRadians+PI/2)) );
PointF B=new PointF( (float)(fCenterX+
fThickness*2*System.Math.Sin(fRadians-PI/2)),
(float)(fCenterY -
fThickness*2*System.Math.Cos(fRadians-PI/2)) );
PointF C=new PointF( (float)(fCenterX+
fLength*System.Math.Sin(fRadians)),
(float) (fCenterY -
fLength*System.Math.Cos(fRadians)) );
PointF D=new PointF( (float)(fCenterX-
fThickness*4*System.Math.Sin(fRadians)),
(float)(fCenterY +
fThickness*4*System.Math.Cos(fRadians) ));
PointF[] points={A,D,B,C};
e.Graphics.FillPolygon( new SolidBrush(color), points );
}
為了使控件的用戶能夠控制這個時鐘控件的啟停,我們在其中加入另外兩個函數。
public void Start()
{
timer1.Enabled=true;
this.Refresh();
}
public void Stop()
{
timer1.Enabled=false;
}
控件對于
Paint
消息的響應函數是這個控件中最核心的程序,完成了時間提取、弧度轉換及畫指針這一系列活動。
代碼如下:
private void AnalogClock_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
float fRadHr=(dateTime.Hour%12+dateTime.Minute/<chmetcnv unitname="F" sourcevalue="60" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">60F</chmetcnv>) *30*PI/180;
float fRadMin=(dateTime.Minute)*6*PI/180;
float fRadSec=(dateTime.Second)*6*PI/180;
DrawPolygon(this.fHourThickness,
this.fHourLength, hrColor, fRadHr, e);
DrawPolygon(this.fMinThickness,
this.fMinLength, minColor, fRadMin, e);
DrawLine(this.fSecThickness,
this.fSecLength, secColor, fRadSec, e);
for(int i=0;i<60;i++)
{
if ( this.bDraw5MinuteTicks==true && i%5==0 )
// Draw 5 minute ticks
{
e.Graphics.DrawLine( new Pen( ticksColor, fTicksThickness ),
fCenterX +
(float)( this.fRadius/<chmetcnv unitname="F" sourcevalue="1.5" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.50F</chmetcnv>*System.Math.Sin(i*6*PI/180) ),
fCenterY -
(float)( this.fRadius/<chmetcnv unitname="F" sourcevalue="1.5" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.50F</chmetcnv>*System.Math.Cos(i*6*PI/180) ),
fCenterX +
(float)( this.fRadius/<chmetcnv unitname="F" sourcevalue="1.65" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.65F</chmetcnv>*System.Math.Sin(i*6*PI/180) ),
fCenterY -
(float)( this.fRadius/<chmetcnv unitname="F" sourcevalue="1.65" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.65F</chmetcnv>*System.Math.Cos(i*6*PI/180)) );
}
else if ( this.bDraw1MinuteTicks==true ) // draw 1 minute ticks
{
e.Graphics.DrawLine( new Pen( ticksColor, fTicksThickness ),
fCenterX +
(float) ( this.fRadius/<chmetcnv unitname="F" sourcevalue="1.5" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.50F</chmetcnv>*System.Math.Sin(i*6*PI/180) ),
fCenterY -
(float) ( this.fRadius/<chmetcnv unitname="F" sourcevalue="1.5" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.50F</chmetcnv>*System.Math.Cos(i*6*PI/180) ),
fCenterX +
(float) ( this.fRadius/<chmetcnv unitname="F" sourcevalue="1.55" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.55F</chmetcnv>*System.Math.Sin(i*6*PI/180) ),
fCenterY -
(float) ( this.fRadius/<chmetcnv unitname="F" sourcevalue="1.55" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1.55F</chmetcnv>*System.Math.Cos(i*6*PI/180) ) );
}
}
//draw circle at center
e.Graphics.FillEllipse( new SolidBrush( circleColor ),
fCenterX-fCenterCircleRadius/2,
fCenterY-fCenterCircleRadius/2,
fCenterCircleRadius, fCenterCircleRadius);
}
最后,還須為此控件設置個三個屬性,使用戶可以更改其顏色。
代碼如下:
public Color HourHandColor
{
get { return this.hrColor; }
set { this.hrColor=value; }
}
public Color MinuteHandColor
{
get { return this.minColor; }
set { this.minColor=value; }
}
public Color SecondHandColor
{
get { return this.secColor; }
set { this.secColor=value;
this.circleColor=value; }
}
3、
在其它工程中應用此控件
在對上述控件工程進行正確編譯后,得到一個
DLL
文件,可以將其拷入其它任意工程文件夾中,右鍵工具欄,選
choose Items…
<shape id="_x0000_i1028" style="WIDTH: 157.5pt; HEIGHT: 228pt" type="#_x0000_t75"><imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image007.png" o:title="" cropbottom="36222f" cropright="49314f"><font face="Times New Roman" size="3"></font></imagedata></shape>
在其后出現的對話框中選
browse
鈕,選擇相應的
dll,
相應的時鐘控件即出現在工具欄中,我們可以對它進行任意拖動。
Enjoy it !
譯自:
例程下載:
C#時鐘控件的創建與使用