以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 Dot NET,C#,ASP,VB 』  (http://bbs.xml.org.cn/list.asp?boardid=43)
----  用VB.NET做个时钟  (http://bbs.xml.org.cn/dispbbs.asp?boardid=43&rootid=&id=11787)


--  作者:admin
--  发布时间:11/9/2004 2:25:00 AM

--  用VB.NET做个时钟


发信人: mydea (请多关照), 信区: DotNET        
标  题: 用VB.NET做个时钟
发信站: BBS 水木清华站 (Sat Dec 15 01:10:58 2001)


是使用GDI+画图的例子
本章最后的综合实例是一个模拟时钟。程序运行时,窗体中模拟一个真实的时钟那样显示当前的时间。
本程序使用了面向对象的编程方法,由于时针(HourHand)、分针(MinuteHand)和秒针(SecondHand)包含相似的属性和方法,我们生成一个针(Hand)类作为它们共同的基类,提供共有的类成员。下面是定义Hand类的代码:
Public MustInherit Class Hand
        Protected gp As GraphicsPath = New GraphicsPath()        
        Protected gpBase As GraphicsPath = Nothing
        Protected midX As Integer = 150                 ‘默认的窗体
        Protected midY As Integer = 150                 ‘中心位置
                ‘构造器,得到窗体中心位置
        Public Sub New(ByVal theForm As Form1)
            midX = (theForm.ClientRectangle.Left + theForm.ClientRectangle.Right) / 2
            midY = (theForm.ClientRectangle.Top + theForm.ClientRectangle.Bottom) / 2
        End Sub
        MustOverride Sub Transform(ByVal d As DateTime)
                ‘绘制指针路径
        Overridable Sub Draw(ByVal g As Graphics)
            Dim aPen As Pen = New Pen(Brushes.Black, 4F)
            g.DrawPath(aPen, gp)
            g.FillPath(Brushes.Black, gp)
            aPen.Dispose()
        End Sub
                ‘使用矩阵实现路径(gp)的旋转
        Public Sub Rotate(ByVal angle As Double)
            gp = CType(gpBase.Clone(), GraphicsPath)
            Dim mTransform As Matrix = New Matrix()
            mTransform.RotateAt(CType(angle,Single),NewPointF(midX,midY))
            gp.Transform(mTransform)
        End Sub
    End Class
为了节省篇幅,上面的代码省略了引入命名空间的语句。
下面是分针(MinuteHand)类的定义:
Public Class MinuteHand
        Inherits Hand
                ‘构造器,生成绘制分针的路径(gp)
        Public Sub New(ByVal myForm As Form1)
            MyBase.New(myForm)
            gp.AddLine(midX, midY, midX, 45)
            gp.AddLine(midX, 45, midX - 3, 50)
            gp.AddLine(midX - 3, 50, midX + 3, 50)
            gp.AddLine(midX + 3, 50, midX, 45)
            gpBase = CType(gp.Clone(), GraphicsPath)
        End Sub
                ‘Transform方法取得系统当前时间,并旋转时钟指针。
        Public Overrides Sub Transform(ByVal d As DateTime)
            Dim minuteTime As Double = (CDbl(d.Minute) + CDbl(d.Second / 60))
            Dim angle As Double = (CDbl(minuteTime) / 60) * 360
            Rotate(angle)
        End Sub
    End Class
对所有的指针旋转的方法都是相同的,因此在基类中实现。由于时针和秒针的实现与分针相似,所不同者,只在于构造器中绘制的指针路径不同和Transform方法中转动的角度不同,在这里就不在赘述了。
另外还需要提一下的是画时钟表面的代码,时钟表面用ClockFace类来实现。这个类首先画一个圆代表时钟,然后画上米老鼠的图案,最后在相应的位置画上数字1~12代表12个小时。
Public Sub Draw(ByVal g As Graphics)
            DrawClockFace(g)
            DrawImage(g)
            DrawNumbers(g)
            DrawPin(g)
End Sub
下面是ClockFace类的属性:
Private ClockRectangle As Rectangle
        Private ClockFont As Font = New Font("Arial", 12)        
        Private midPoint As Point
        Private ClockImage As Bitmap
        Private Const IMAGEX As Integer = 50
        Private Const IMAGEY As Integer = 50
DrawClockFace方法用来画时钟表面:
Private Sub DrawClockFace(ByVal g As Graphics)
            g.FillEllipse(Brushes.White, ClockRectangle.Left + 10, ClockRectangle.Top + 10, ClockRectangle.Width - 20, ClockRectangle.Height - 20)
            g.DrawEllipse(Pens.Black, ClockRectangle.Left + 10, ClockRectangle.Top + 10, ClockRectangle.Width - 20, ClockRectangle.Height - 20)
End Sub
然后用Graphics对象的DrawImage方法画出米老鼠的图片:
Private Sub DrawImage(ByVal g As Graphics)
            Dim nWidth As Integer = ClockImage.Width
            Dim nHeight As Integer = ClockImage.Height
            Dim destRect As Rectangle = New Rectangle(midPoint.X - IMAGEX / 2, midPoint.Y - IMAGEY / 2, IMAGEX, IMAGEY)
            g.DrawImage(ClockImage, destRect)
End Sub
数字在时钟上的位置是用sin和cos函数计算的:
Private Sub DrawNumbers(ByVal g As Graphics)
            Dim count As Integer = 1
            Dim a As Double
            For a = 0 To 2 * Math.PI Step 2 * Math.PI / 12
            Dim x As Double = (ClockRectangle.Width - 70) / 2 * Math.Cos(a - Math.PI / 3) + (ClockRectangle.Width - 70) / 2 + 25
            Dim y As Double = (ClockRectangle.Width - 70) / 2 * Math.Sin(a - Math.PI / 3) + (ClockRectangle.Width - 70) / 2 + 20
                g.DrawString(Convert.ToString(count), ClockFont, Brushes.Black, CType(x, Single), CType(y, Single), New StringFormat())
                count += 1
            Next
End Sub
最后是窗体文件(Form1.vb):
Public Class Form1
        Inherits System.Windows.Forms.Form
        Private MyMinuteHand As MinuteHand
        Private MyHourHand As HourHand
        Private MySecondHand As SecondHand
        Private TheClockFace As ClockFace
        Private FirstTick As Boolean = False
                ‘在窗体的OnPaint事件中取得Graphics对象
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            If (FirstTick = False) Then Exit Sub
            Dim g As Graphics = e.Graphics
            TheClockFace.Draw(g)
            MyHourHand.Draw(g)
            MyMinuteHand.Draw(g)
            MySecondHand.Draw(g)
            TheClockFace.DrawPin(g)
        End Sub
                ‘计时器事件
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            MySecondHand.Transform(DateTime.Now)
            MyHourHand.Transform(DateTime.Now)
            MyMinuteHand.Transform(DateTime.Now)
            FirstTick = True
            Invalidate()         
‘此方法继承自Control类,使控件失效而导致窗体重绘(即再次调用OnPaint事件)
        End Sub
    End Class
注意要在Form1类的构造器中键入下列代码:
MyMinuteHand = New MinuteHand(Me)
MyHourHand = New HourHand(Me)
MySecondHand = New SecondHand(Me)
TheClockFace = New ClockFace(ClientRectangle)
在Dispose方法中键入
timer1.Start()
图13-9为程序执行时显示的效果:

--

※ 来源:·BBS 水木清华站 smth.org·[FROM: 162.105.106.97]
上一篇
返回上一页
回到目录
回到页首



W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
62.500ms