VB设计有语音报时和报警功能的闹钟
2004-05-18■作者:潇潇■出处: Yesky开发者网络
从钟表的制作兼谈数学在编程中的应用
经常在论坛上看到很多刚刚想要步入编码领域的爱好者问道:我数学学的不好,能学好编程吗?当然回答的人也各自有不同的答案。但我要说,随着编程工具功能的日臻完善,工具所能做的越来越多,大大提高了程序员的开发速度,因此如果只是玩玩编程的话,对于数学不许要太多的专业知识,单是各个工具中提供的控件,就足以让你编写出一个让你感到自豪的软件了;而对于逻辑方面的问题,只要没有智力问题,说话不颠三倒四的,应该也不会有什么问题。但是对于一个计算机专业的工作者,或者想要成为一名计算机专业领域工作者的爱好者,数学就是必须学习的知识了,而且越是和图形打交道多的领域,对数学的运用越多。
所以这里我们就以一个很小的程序来看一看数学在编程中的应用。
先来看一看,我们想要实现的功能吧。作为一个有实在意义的时钟,除了显示时间,还要能够定时、报时等等。所以我们在这个例子中,就要实现以下几种功能:
1、 显示时间 2、定时报警 3、语音报时 4、定时关机
(一)显示时间
让我们先来看看怎样实现显示时间吧。在windows中给我们提供了一系列通用控件,而且各种编程工具又在这个基础上,给我们提供了更多的选择。不同的控件,有不同的作用,但就显示信息来说,主要有textbox,Lable等控件。在这里我们选择Lable控件来显示时间。
那么怎样获取时间呢?vb中给我们提供了以下函数:
函数名
函数功能
语法结构
Date 函数
返回包含系统日期的Variant( Date ) 。
Date
DateAdd函数
返回包含一个日期的Variant( Date ) ,这个日期还加上了一段时间间隔。
DateAdd ( interval ,number ,date )
DateDiff函数
返回Variant( Long )的值,表示两个指定日期间的时间间隔数目。
DateDiff ( interval ,date1 ,date2,firstdayofweek [,firstweekofyear ] )
DatePart函数
返回一个包含已知日期的指定时间部分的Variant( Integer )
DatePart( interval ,date
[ , firstdayofweek ]
[ , firstweekofyear ] )
DateSerial函数
返回包含指定的年月日的Variant( Date )
DateSerial( year ,month ,day )
DateValue函数
返回一个Variant( Date )
DateValue( date )
Day函数
返回一个Variant( Integer ) ,其值为1到31之间的整数,表示一个月中的某一日
Day( date )
Hour函数
返回一个Variant ( integer ) ,其值为0到23之间的整数,表示一天之中的某一个钟点
Hour ( time )
Minute函数
返回一个Variant ( Integer ) ,其值为0到59之间的整数,表示一个小时中的某一分钟
Minute ( time )
Now函数
返回一个Variant ( Date ) ,根据计算机系统设置的日期和时间来指定日期和时间
Now
Second函数
返回一个Variant( Integer ) ,其值为0到59之间的整数,表示一分钟之内的某一秒钟
Second( time )
Time函数
返回一个指明当前系统时间的Variant( Date )
Time
Time语句
设置系统时间
Time = time
Timer函数
返回一个Single,代表从午夜开始到现在所经过的秒数
Timer
TimeSerial函数
返回一个Variant( Date ) ,包含具有现在时、分、秒的时间。
TimeSerial(hour,minute,second)
TimeValue函数
返回一个包含时间的Variant( Date )
TimeValue( time )
Weekday函数
返回一个Variant ( Integer ) ,包含一个整数,代表某个日期是星期几
Weekday( date
[ ,firstdayofweek ] )
Year函数
返回一个Variant( Integer ) ,包含表示年份的整数
Year( date )
多丰富的资源,vb真是体贴。下面然我们来以一个实例看看怎样显示时间吧。
程序中所用到的控件的作用和相关属性设置如下表:
控件
属性
值
作用
Form1
Caption
时钟
显示窗体
Label1
Caption
空
显示时间
Label2
Caption
空
显示分钟
Label3
Caption
空
显示秒钟
Label4
Caption
空
显示年份
Label5
Caption
空
显示月份
Label6
Caption
空
显示日期
Label7
Caption
空
显示星期几
Timer1
Interval
1000
每秒钟触发一次事件
下面是代码:
Private Sub Timer1 _ Timer ( )
hou = Hour ( Time )
miu = Minute ( Time )
sec = Second ( Time )
yea = Year ( Date )
mon = Month ( Date )
da = Day ( Date )
Label1 . Caption = hou & "小时 "
Label2 . Caption = miu & "分钟"
Label3 . Caption = sec & "秒钟"
Label4 . Caption = yea & "年"
Label5 . Caption = mon & "月"
Label6 . Caption = da & "日"
Label7 . Caption = "星期" & Weekday ( Date )
End Sub
下图是运行的结果:
很简单吧!下面我们看看不使用控件,我们用绘图函数自己来画出一个运行着的时钟。
现来补充一些v b中的绘图知识:
1、Line方法
Line方法用于画出一条直线或矩形,其语法格式如下:
格式:[对象] . Line [ [ Step ] ( x1 , y1 ) ] -( x2 ,y2 )[ ,颜色 ] [ ,B [ F ] ]
说明:
(1)对象指的是Line在何处产生结果,它可以是窗体或图形框,默认为当前窗体;
(2)( x1 ,y1 )为线段的起点坐标或矩形的左上角坐标;
(3)(x2,y2)为线段的终点坐标或矩形的右下叫坐标;
(4)关键字Step表示采用当前作图位置的相对值;
(5)关键字B表示画矩形;
(6) 关键字F表示用画矩形的的颜色来填充矩形。缺省F时,矩形的填充由FillColor和FillStyle属性决定。
举个例子:我们在窗体上随机画20条颜色不同得直线.可以这样写:
Private Sub Form _ Click ( )
Dim i As Integer
Dim x As Integer
Dim y As Integer
For i = 1 To 20
x = Form1 . ScaleWidth * Rnd
y = Form1 . ScaleHeight * Rnd
Clr = 15 * Rnd
Line ( Form1 . Width / 2 , Form1 . Height / 2 ) - ( x , y ) , QBColor ( Clr )
Next i
End Sub
下面是运行结果:
2、Circle方法
Circle方法用于画圆、椭圆、圆弧和扇形,其语法格式如下:
格式: [对象.] Circle [ [ Step ] ( x , y ) ,半径 [ ,颜色 ] [ ,起始角度 ] [ ,终止角度 ] [ ,长短轴比率 ] ]
说明:
(1) 对象指的是Circle方法将在何处产生结果,它可以是窗体或图形框或打印机,缺省时为当前窗体。
(2)(x,y)为圆心坐标,关键字Step表示采用当前作图位置的相对值。
(3)圆弧和扇形通过参数的起始角度和终止角度控制。当起始角度和终止角度取值为0~360度时,画出来的是圆弧;当在起始角度和终止角度取值前加一个负号时,画出的是扇形,负号表示要画圆心到圆弧的径向线。
(4)椭圆通过长短轴比率控制,默认值为1,所以画出来的是圆。
下面我们用Circle方法分别画出圆形,椭圆,圆弧和扇形。下面是代码和图示:
Private Sub Form _ Click ( )
Circle (1500, 1500), 1000
End Sub
下图为画出的圆形:
Private Sub Form _ Click ( )
Circle ( 1500, 1500 ) , 1000 , , 0.7 , 2.1 ‘注意1000和0.7,中间是两个逗号
End Sub
下图为画出的圆弧:
Private Sub Form _ Click ( )
Circle (1500 , 1500 ) , 1000 , , - 0.7 , - 2.1
End Sub
下图为画出的圆形:
Private Sub Form _ Click ( )
Circle ( 1500 , 1500 ) , 1000 , , , , 0.5
End Sub
下图为画出的椭圆形:
3、Pset方法
Pset方法用于画点,其语法格式如下:
格式: [对象 . ] Pset [ Step ] ( x , y ) [ ,颜色 ]
说明:
(1)参数(x,y)为所画点的坐标
(2)关键字Step表示采用当前作图位置的相对值
(3)采用背景颜色可清除某个位置上的点,利用Pset方法可画出任意的曲线
下面我们来看一个例子.我们用Pset方法在窗体上面绘制阿基米德螺线.下面是代码和运行结果:
Private Sub Form _ Activate ( )
Dim x As Single
Dim y As Single
Dim z As Single
Scale ( - 20 , 20 ) - ( 20 , - 20 )
Line ( 0 , 17 ) - ( 0 , - 17 )
Line ( 18 , 0 ) - ( - 18 , 0 )
For z = 0 To 15 Step 0.01
y = z * Sin ( z )
x = z * Cos ( z )
PSet ( x , y )
Next z
End Sub
运行结果如下:
到现在为止,应该说我们关于编程方面的知识已经足够了.但应该怎样画出一个钟表的准确位置呢?也就是说我们怎样在窗体中确定每一个刻度呢?
肯定得用到三角函数了.让我们一起简单的回顾以下,在高中时所学的三角函数的知识吧.
我们知道,三角函数主要有这样几个公式:
sin ( a ) = 对边a / 斜边c
cos ( a ) = 底边b / 斜边c (其中角度a,可以是任意角度)
如下图所示:
由图可知,在一周之内,角度a可以在从0度到360度取值而对于钟表来说,每个刻度之间的度数差别为360度除以60个刻度,等于6度,也就是说公式里的角度a已经知道了.而且可知边a实际上就是圆上任意一点在y轴上的坐标,而边b是加上就是圆上任意一点在x轴上的坐标,半径r由我们所要画出的圆形的大小决定的,所以我们可以得到圆上任意一点在坐标系中的x , y轴上的取值.公式如下:
x = sin ( a ) * r
y = cos ( a ) * r
而且在vb中,也有这样的函数可供使用.
1、cos函数
作用:返回一个Double,指定一个角度的余弦值
格式: Cos(number)
2、sin函数
作用:返回一个Double,指定一个角度的正弦值
格式: Sin(number)
下面我们通过示例来看看具体的用法。
首先,我们将用这些知识来画出一个正弦:
下面是代码:
'=======================
'说明,x从0到form1的最右面
'y值中,因为i是从0变到form1的最右面
'所以i/form1.scalewidth 就从0 变到1
'所以,i/form1.scalewidth*2*3.1415926既是o*2pi 到1* 2pi
'所以,cos(i/form1.scalewidth*2*3.1415926),就从1到-1,在变到1
'所以,1-cos(i/form1.scalewidth*2*3.1415926),就从0到2,在变到0
'所以y 就从0到form1.scaleheight,在变到0
'即可画出cos曲线
'=======================
Private Sub huacos ( ) ‘自定义了一个名为huacos的过程
Dim x As Double
Dim y As Double
For i = 0 To Form1 . ScaleWidth ‘设定周期为Form1 . ScaleWidth
x = i
y = ( 1 – Cos ( i / Form1 . ScaleWidth * 2 * 3.1415926 ) ) * Form1 . ScaleHeight / 2
‘ 因为三角函数中的角度的增长方向,和计算机中相反,所以要用1减去cos值
PSet ( x , y )
Next i
End Sub
Private Sub Form _ Activate ( )
Huacos ‘调用huacos 过程
End Sub
下图为运行结果:
余弦和它相似,代码如下:
Private Sub huasin ( ) ‘自定义了一个名为huasin的过程
Dim x As Double
Dim y As Double
For i = 0 To Form1 . ScaleWidth ‘设定周期为Form1 . ScaleWidth
x = i
y = (1 – Sin ( i / Form1 . ScaleWidth * 2 * 3.1415926 ) ) * Form1 . ScaleHeight / 2
‘ 因为三角函数中的角度的增长方向,和计算机中相反,所以要用1减去sin值
PSet (x, y)
Next i
End Sub
Private Sub Form _ Activate ( )
huasin ‘调用huasin过程
End Sub
下图为运行结果:
有了这些基础,画出一个正圆也就没问题了。请看下面的代码。
Private Sub huayuan ( )
Dim x As Double
Dim y As Double
For i = 0 To 360
x = (1 – Sin ( i / 360 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 100 ) + 100
y = (1 – Cos ( i / 360 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 100 ) + 100
Pset ( x , y )
Next i
End Sub
Private Sub Form _ Activate ( )
huayuan
End Sub
上面的代码不难,好好思考一下吧.下面是运行结果:
上面的例子里,我们使用360个点组成了一个密集度挺高的圆形,可是既然v b中已给我们提供了现成的画圆形的函数,为什么不用呢?但通过上面的例子,我们应该想到,如果我们将360个点,变成60个点,那不就正好是一个钟表的刻度吗?!这样的话我们只需要改动两个地方,一个是点的个数,另一个是点与点之间的弧度,应该为360度的60分之一,也就是每60度画一个点。代码如下:
Private Sub huabiaopan ( )
Dim x As Double
Dim y As Double
For i = 0 To 60
x = ( 1 – Sin ( i / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 100 ) + 100
y = ( 1 – Cos ( i / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 100 ) + 100
PSet ( x , y )
Next i
End Sub
Private Sub Form _ Activate ( )
huabiaopan
End Sub
下面是运行结果: (为了看得清楚些,我将颜色设为了红色,大家可以随喜好自行修改,方法当然是在Pset函数中了)
看来我们距离成功越来越近了。对于钟表里的三个针来说,每一时刻都会指向其中一个刻度,所以我们只要在其中添加代码,让它实现从圆心到所指刻度画直线就可以实现钟表里的三个针了。
下面是关于其中一个针的走动,代码如下:
Private Function huamiao ( a As Integer )
'用同背景相同的颜色,在前一次的位置上,从新画直线,抹除前一次画的线
x = (1 – Sin ( ( a + 1 ) / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 200 ) + 200
y = ( 1 – Cos ( ( a + 1 ) / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 200 ) + 200
Line ( Form1 . ScaleHeight / 2 , Form1 . ScaleHeight / 2 ) - ( x , y ) , QBColor ( 7 )
'然后开始画後一秒的线
x = (1 – Sin (a / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 200 ) + 200
y = (1 – Cos ( a / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 200 ) + 200
Line ( Form1 . ScaleHeight / 2 , Form1 . ScaleHeight / 2 ) - ( x , y ) , QBColor ( 1 )
huamiao = a - 1
End Function
Private Sub Timer1 _ Timer ( )
mz = Second ( Time )
mz = 60 – mz ‘因为三角函数中,角度的变化方向,正好与钟表的方向相反,
‘所以60减去就相当于将角度变为负值,也就是说,和原来的角‘度增长方向正好相反,与钟表的增长方向相同。
mz = huamiao ( mz )
End Sub
下面是运行效果:
好了,现在我们可以加上,分针和时针了.下面是源代码和运行结果:
' = = = = = = = = = = = = = = = = = = = = = =
' 以下语句能画出表盘
‘ 六十个点表示六十个刻度,
' = = = = = = = = = = = = = = = = = = = = = =
Private Sub huayuan ( )
Dim x As Double
Dim y As Double
For i = 0 To 60
x = ( 1 – Sin ( i / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 100 ) + 100
y = ( 1 – Cos ( i / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 100 ) + 100
PSet ( x , y ) , QBColor ( 12 )
Next i
End Sub
‘ = = = = = = = = = = = = = = = = = = = = = = = = = =
‘下面代码作用是画出时针走的路线
‘时针是12个刻度,表示是12个钟点
‘ = = = = = = = = = = = = = = = = = = = = = = = = = =
Private Function xianshishi ( a As Integer )
'抹除前一次画的线
x = (1 – Sin ( ( a + 1 ) / 12 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 800 ) + 800
y = (1 – Cos ( ( a + 1 ) / 12 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 800 ) + 800
Line ( Form1 . ScaleHeight / 2, Form1 . ScaleHeight / 2 ) - ( x , y ) , QBColor ( 7 )
'开始画後一秒的线
x = ( 1 – Sin ( a / 12 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 800 ) + 800
y = ( 1 – Cos ( a / 12 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 800 ) + 800
Line ( Form1 . ScaleHeight / 2 , Form1 . ScaleHeight / 2 ) - ( x , y ) , QBColor ( 1 )
xianshishi = a - 1
End Function
‘ = = = = = = = = = = = = = = = = = = = = = = = = = =
‘下面代码作用是画出秒针走的路线
‘秒针是六十个刻度,表示是六十个秒点
‘ = = = = = = = = = = = = = = = = = = = = = = = = = =
Private Function xianshimiao ( a As Integer )
'抹除前一次画的线
x = ( 1 – Sin ( ( a + 1 ) / 59 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 200 ) + 200
y = ( 1 – Cos ( ( a + 1 ) / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 200 ) + 200
Line ( Form1 . ScaleHeight / 2, Form1 . ScaleHeight / 2 ) - ( x , y ) , QBColor ( 7 )
'开始画後一秒的线
x = (1 – Sin ( a / 59 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 200 ) + 200
y = ( 1 – Cos ( a / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 200 ) + 200
Line ( Form1 . ScaleHeight / 2 , Form1 . ScaleHeight / 2 ) - ( x , y ) , QBColor ( 1 )
xianshimiao = a - 1
End Function
‘ = = = = = = = = = = = = = = = = = = = = = = = = = =
‘下面代码作用是画出分针走的路线
‘分针是六十个刻度,表示是六十个分点
‘ = = = = = = = = = = = = = = = = = = = = = = = = = =
Private Function xianshifen ( a As Integer )
'抹除前一次画的线
x = (1 – Sin ( ( a + 1 ) / 59 * 2 * 3.1415926 ) ) * ( Form1.ScaleHeight / 2 – 400 ) + 400
y = ( 1 – Cos ( ( a + 1 ) / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 400 ) + 400
Line ( Form1 . ScaleHeight / 2 , Form1 . ScaleHeight / 2 ) - ( x , y ) , QBColor ( 7 )
'开始画後一秒的线
x = (1 – Sin ( a / 59 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 400 ) + 400
y = (1 – Cos ( a / 60 * 2 * 3.1415926 ) ) * ( Form1 . ScaleHeight / 2 – 400 ) + 400
Line ( Form1 . ScaleHeight / 2 , Form1.ScaleHeight / 2 ) - ( x , y ) , QBColor ( 1 )
xianshifen = a - 1
End Function
‘ = = = = = = = = = = = = = = = = = = = = = = = =
‘ 每秒钟触发一次此事件,从而获取当时的时间,并调用相应的函数,画出三个针的位置
‘ = = = = = = = = = = = = = = = = = = = = = = = =
Private Sub Timer1 _ Timer ( )
miao = Second ( Time )
miao = 60 – miao
fen = Minute ( Time )
fen = 60 - fen
shi = Hour ( Time )
If shi > = 12 Then ‘因为一天之内时针要走二十四个钟头,也就是要走两圈,所以将下午和晚上的时间减去十二,就可以确定时针准确的位置
shi = shi - 12
End If
shi = 12 - shi
miao = xianshimiao ( miao )
fen = xianshifen ( fen )
shi = xianshishi ( shi )
End Sub
‘ = = = = = = = = = = = = = = = =
‘此事件,在窗体最初载入时触发,主要作用是画出表盘和刻度
‘ = = = = = = = = = = = = = = = =
Private Sub Form _ Load ( )
Form1 . Width = Form1 . Height - 250
Huayuan ‘画刻度
Form1 . Circle ( Form1 . ScaleHeight / 2 , Form1 . ScaleHeight / 2 ) , Form1 . ScaleHeight / 2 - 30
End Sub
运行效果如下图所示:
(二) 语音报时
下面我们再继续个它添加语音报时的功能.其实很简单,主要思路就是获取当前时间,如果是整点(即,分针,时针都为零)时,我们可以运用MCI ( Media Control Interface , 媒体控制接口)来播放,你已经录好的报时的声音文件.下面我们具体来看一看怎样实现这一功能.
现来了解一下MCI . MCI是Windows提供的一个可以处理音频和视频的API(应用程序编程接口),通过它,我们可以很方便的实现对音频设备,和视频设备及其其他设备的控制.这一接口极大的方便了使用者,使我们可以只使用设备接口,而不用对实际的物理设备进行直接的操作.
为了使用mci我们首先要点取Project ( 工程 ) / Components (组件)菜单,或在工具箱中点击右键,然后在弹除的菜单中选择部件,这时屏幕上会弹出如图所示的对话框.
在其中选中”microsoft Multimedia Control”,在单击确定按钮,就可以把MMControl控件添加到工具箱中了.当把MMControl控件添加到窗体中时,她的形状如下所示:
上面的九个按钮,分别表示九种功能.和普通的录音机上的按钮类似,从左到右分别是:Prev (向前) , Next (向后) , Play (播放) , Pause (暂停) , Back (快速倒带) , Step (快速进带) , Record ( 录音 ) ,和Eject (弹出).
使用时,先要为MMContorl控件指定一个要播放的文件,然后用Open命令打开它.然后再使用Play命令播放文件.最后关闭所打开的文件.
下面我们看看怎样用MMControl来实现语音报时功能.
下面是代码(我们这里主要给出所改动的地方):
‘ = = = = = = = = = = = = = = = = = = = = = = = =
‘ 每秒钟触发一次此事件,从而获取当时的时间,并调用相应的函数,画出三个针的位置
‘ = = = = = = = = = = = = = = = = = = = = = = = =
Private Sub Timer1 _ Timer ( )
miao = Second ( Time )
miao = 60 – miao
fen = Minute ( Time )
fen = 60 - fen
shi = Hour ( Time )
If shi > = 12 Then ‘因为一天之内时针要走二十四个钟头,也就是要走两圈,所以将下午和晚上的时间减去十二,就可以确定时针准确的位置
shi = shi - 12
End If
shi = 12 - shi
miao = xianshimiao ( maio )
fen = xianshifen ( fen )
shi = xianshishi ( shi )
If fen = 0 and miao = 0 then ‘如果分针和秒针都为零,这位整点,根据时针的数报时
Select case shi
Case 0 ‘零点,0.wav报时零点
MMControl1 . FileName = App . Path & “ 0.wav ” ‘选择要打开的文件
MMControl1 . Commond = “ Open ” ‘打开所选择的文件
MMControl1 . Commond = “ Play ” ‘播放所选择的文件
Case 1 ‘ 一点,1.wav报时一点,以下依次类推
MMControl1 . FileName = App . Path & “ 1.wav ” ‘选择要打开的文件
MMControl1 . Commond = “ Open ” ‘打开所选择的文件
MMControl1 . Commond = “ Play ” ‘播放所选择的文件
Case 2
MMControl1 . FileName = App . Path & “ 2.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 3
MMControl1 . FileName = App . Path & “ 3.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 4
MMControl1 . FileName = App . Path & “ 4.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 5
MMControl1 . FileName = App . Path & “ 5.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 6
MMControl1 . FileName = App . Path & “ 6.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 7
MMControl1 . FileName = App . Path & “ 7.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 8
MMControl1 . FileName = App . Path & “ 8.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 9
MMControl1 . FileName = App . Path & “ 9.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 10
MMControl1 . FileName = App . Path & “ 10.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 11
MMControl1 . FileName = App . Path & “ 11.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
End Select
MMControl1.Commond = “ Close ”
End Sub
不知道你的机子是否还能运行良好.毕竟再短短的一秒钟内,我们让计算机做的事情太多了.为了提高效率,我们可以考虑使用API函数.
我们先来看一下所要用到的相关知识.
1、 GetLocalTime
VB声明:Declare Sub GetLocalTime Lib " kernel32 " Alias " GetLocalTime " ( lpSystemTime As SYSTEMTIME )
说明:在lpSystemTime结构中装载本地日期和时间
参数:GetLocalTime函数只有一个参数lpSystemTim,指向SYSTEMTIME结构,用于装载本地时间的结构。
2、SYSTEMTIME结构
定义:Public Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type
说明:SYSTEMTIME结构表示一个日期和时间,年、月、日、星期、时、分、秒、毫秒各用一个成员来表示。其中wYear 为Integer型,表示当前的年份;wMonth 为 Integer型,表示当前的月份,从1月到12月分别用1到12来表示; wDayOfWeek 为 Integer型,表示当前的星期,从星期日开始,分别用0到6个数表示; wDay 为 Integer型,表示当前的日期; wHour 为 Integer型,表示当前的时刻; wMinute 为 Integer型,表示当前的分钟; wSecond 为 Integer型,表示当前的秒; wMilliseconds 为 Integer型,表示当前的毫秒。
3、mciExecute ()
vb声明: Public Declare Function mciExecute Lib " winmm.dll " Alias " mciExecute " ( ByVal lpstrCommand As String ) As Long
说明: mciExecute ( )函数用来传送一个命令字符串给MCI,以实现各种播放功能。
它的返回值为Long型值,如果返回值为0,表示调用失败,如果返回值不为0,表示调用成功。MciExecute ( )函数的参数只有一个lpstrCommand,为String型,表示MCI的命令字符串。
MCI的命令字符串共有7个,其名称、功能及其用法如下表:
名称
语法形式
说明
open
Open CDAudio alias CD
Open命令的功能是打开一个CDAudio设备,其中CDAudio为设备名;alias为赋予CDAudio设备的一个别名。
例如,要打开一个设备名称为CD的设备,我们可以这样写语句:mciExecute “open cdaudio alias cd”
close
Close 设备别名
Close命令的功能是关闭一个已经打开的CDAudio设备。
例如,要关闭一个设备名称为CD的设备,我们可以这样写语句:mciExecute “close cd”
play
Play 设备别名 from [position1] to [position2]
Play命令的功能是播放一个已经打开的CDAudio设备上的CD音乐。参数from [position1] to [position2] 指定CDAudio播放的起始位置和结束位置,如果省略,就从开始点播放到终点。
例如,要从开始点播放CDAudio设备上的CD音乐,我们可以这样写语句:mciExecute “play cd”
stop
Stop 设备别名
Stop命令的功能是停止一个正在播放的CDAudio设备上的CD音乐。
例如,要停止播放CDAudio设备上的CD音乐,我们可以这样写语句:mciExecute “stop cd”
seek
Seek 设备别名 参数
Seek命令的功能是搜索CDAudio设备上的指定位置。其中的参数有三种:(1)to position :移动到程序指定的位置(2)to start:移动到起始位置(3)to end:移动到结束的位置。
例如,要跳到CDAudio设备上的结束位置,设备别名为CD,我们可以这样写:mciExecute “ seek cd to end ”
set
Set 设备别名 参数
Set命令的功能是设置CDAudio设备的状态。其中的参数为:(1)Audio all on :关闭声音输出;(2)Audio all on :打开声音输出;(3)Audio left on :打开左声道声音输出;(4)Audio left off : 关闭左声道声音输出; (5)Audio right on :打开右声道声音输出; (6)Audio right off :关闭右声道声音输出; (7) Door open : 退出CD光牒 (8) Door closed : 合上光驱(8)Time format milliseconds :设置时间格式为毫秒
例如,我们要实现单声道(左声道)输出声音的效果,可以这样写:mciExecute “ set cd audio left on ”
mciExecute “ set cd audio right off ”
status
Status 设备别名 参数
Status命令的功能是获取已经打开的CDAudio设备上的信息。此命令的参数说明如下: (1) Length : CD 光碟的时间长度; (2) Mode : CDAudio 设备的状态; (3) Position:当前的位置;(4) start position : CD 光碟的起始位置 ; (5) Time format : 当前的时间格式; (6) Numer of track : CD光碟的轨道数
4、mciSendString ()
vb声明: Public Declare Function mciSendString Lib " winmm . dll " Alias " mciSendStringA " ( ByVal lpstrCommand As String , ByVal lpstrReturnString As String , ByVal uReturnLength As Long , ByVal hwndCallback As Long ) As Long
说明: mciSendString()函数的功能与mciExecute()函数相似,也是发送一个命令字符串给MCI,但是mciSendString()函数再传送字符串的同时还可以接受反馈的信息。
MciSendString()函数的返回值为Long型值,如果返回值为0,表示调用失败;如果返回值不为0,表示调用成功。
MciSendString()的参数说明如下:
(1)lpstrCommand : 传送给MCI的命令字符串;
(2)lpstrReturnString : 指向一个预备接受信息的文本缓冲区;
(3)uReturnLength : 所指定的文本缓冲区大小;
(4)hwndCallback : 用来接受确认信息的LpstrCommand,代表传送给MCI的命令字符串。
下面是lpstrCommand参数的取值:
( 1 ) open
语法形式:open 设备名称 参数
功能: 打开一个AVI动画播放设备。
说明:open命令的参数有[ 1 ] Alias : 设备别名 ;[ 2 ] Parent :播放动画窗口的父窗口;[ 3 ] style_sype : 显示动画的窗口类型 ; [ 4 ] style child : 播放动画的为子窗口 ; [ 5 ] style overlapped : 播放动画的为重叠窗口 ; [ 6 ] style popup : 播放动画的为突显示窗口 ;
[ 6 ] style device_type_AVI : 播放的设备.
( 2 ) play
语法形式: play 设备名称 参数
功能: 播放动画文件
说明: play 命令的参数有 [ 1 ] From position1 to position2 : 指定的开始位置播放到指定的结束位置; [ 2 ] Fullscreen : 以全屏幕的方式播放动画文件; [ 3 ] Windows : 在默认的窗口中播放动画文件.
( 3 ) cue
语法形式: cue 设备名称 参数
功能: 准备实例供播放使用
说明: cue命令参数有 [ 1 ] output : 准备一个实例供播放使用; [ 2 ] to position : 跳到指定位置,并且处于暂停状态.
下面是修改后的源代码:
Public Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type
Public Declare Sub GetLocalTime Lib " kernel32 " Alias " GetLocalTime " ( lpSystemTime As SYSTEMTIME )
Public Declare Function mciSendCommand Lib " winmm.dll " Alias " mciSendCommandA " ( ByVal wDeviceID As Long , ByVal uMessage As Long , ByVal dwParam1 As Long , ByVal dwParam2 As Any ) As Long
Public Declare Function mciSendString Lib " winmm.dll " Alias " mciSendStringA " ( ByVal lpstrCommand As String , ByVal lpstrReturnString As String , ByVal uReturnLength As Long , ByVal hwndCallback As Long ) As Long
Dim dangqianshijian AS SYSTEMTIME
‘ = = = = = = = = = = = = = = = = = = = = = = = =
‘ 每秒钟触发一次此事件,从而获取当时的时间,并调用相应的函数,画出三个针的位置
‘ = = = = = = = = = = = = = = = = = = = = = = = =
Private Sub Timer1 _ Timer ( )
Call GetLocalTime( dangqianshijian )
miao = dangqianshijain . wSecond
miao = 60 – miao
fen = dangqianshijian . wMinute
fen = 60 - fen
shi = dangqianshijian . wHour
If shi >= 12 Then ‘因为一天之内时针要走二十四个钟头,也就是要走两圈,所以将下午和晚上的时间减去十二,就可以确定时针准确的位置
shi = shi - 12
End If
shi = 12 - shi
miao = xianshimiao ( maio )
fen = xianshifen ( fen )
shi = xianshishi ( shi )
If fen = 0 and miao = 0 then ‘如果分针和秒针都为零,这位整点,根据时针的数报时
Select case shi
Case 0 ‘零点,0.wav报时零点
MMControl1 . FileName = App . Path & “ 0.wav ” ‘选择要打开的文件
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256, 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ”, ReturnStr , 256 , 0 )
‘播放所选择的文件
Case 1 ‘ 一点,1.wav报时一点,以下依次类推
MMControl1 . FileName = App . Path & “ 1.wav ” ‘选择要打开的文件
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnStr , 256 , 0 )
‘播放所选择的文件
Case 2
MMControl1 . FileName = App . Path & “ 2.wav ”
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnSt r , 256 , 0)
‘播放所选择的文件
Case 3
MMControl1 . FileName = App . Path & “ 3.wav ”
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnStr , 256 , 0 )
‘播放所选择的文件
Case 4
MMControl1 . FileName = App . Path & “ 4.wav ”
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnStr , 256 , 0 )
‘播放所选择的文件
Case 5
MMControl1 . FileName = App . Path & “ 5.wav ”
ErrorCode = mciSendString ( “ Open ” & App.Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnStr , 256 , 0 )
‘播放所选择的文件
Case 6
MMControl1 . FileName = App . Path & “ 6.wav ”
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnStr , 256 , 0 )
‘播放所选择的文件
Case 7
MMControl1 . FileName = App . Path & “ 7.wav ”
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0 . wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnStr , 256 , 0 )
‘播放所选择的文件
Case 8
MMControl1 . FileName = App . Path & “ 8.wav ”
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnStr , 256 , 0 )
‘播放所选择的文件
Case 9
MMControl1 . FileName = App . Path & “ 9.wav ”
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnStr , 256 , 0 )
‘播放所选择的文件
Case 10
MMControl1 . FileName = App . Path & “ 10.wav ”
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0)
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnSt r , 256 , 0)
‘播放所选择的文件
Case 11
MMControl1 . FileName = App . Path & “ 11.wav ”
ErrorCode = mciSendString ( “ Open ” & App . Path & “ 0.wav ” & “ type WaveAudio alias wave ” , ReturnString , 256 , 0 )
‘打开所选择的文件
ErrorCode = mciSendString ( “ Play wave ” , ReturnStr , 256 , 0 )
‘播放所选择的文件
End Select
ErrorCode = mciSendString ( “ Close wave ” , ReturnStr , 256 , 0 )
End Sub
以上修改,因为结构上没有本质变化,都要临时载入wave文件,所以速度上没有质的改变,但我们应该知道因为vb中的函数也都是对windows提供的API的封装,所以,直接调用API效率要高于使用vb所提供的语句和函数.
(三)定时关机和定时报警
对于这两个内容,其实原理是相同的,只是功能不同罢了.下面我们来分析一下它的实现方法.这两个功能都是时时比较设定的时间和当前时间,如果相同,则触发事件,对于定时关机来说就是调用ExitWindowsEx ( ) 函数.而定时报警可以用任何方式 ( 如声音,或形象) 来引起使用者注意.
我们先来看看ExitWindowsEx ( ) 函数的相关知识.
ExitWindowsEx ( )
Vb声明: Declare Function ExitWindowsEx Lib " user32 " Alias " ExitWindowsEx " ( ByVal uFlags As Long , ByVal dwReserved As Long ) As Long
说明: 退出windows,并用特定的选项重新启动, 返回值为 Long 型,非零表示成功,零表示失败。会设置GetLastError
参数表
参数
类型及说明
uFlags
Long,指定下述一个或多个标志(用OR运算符合并到一起)
EWX_FORCE
强迫中止没有响应的进程
EWX_LOGOFF
中止进程,然后注销
EWX_SHUTDOWN
关掉系统电源(如果可能的话,ATX电源就可以)
EWX_REBOOT
重新引导系统
EWX_SHUTDOWN
关闭系统
dwReserved
Long,保留,设为零
这个函数调用后会立刻返回,系统关闭过程是在后台进行的。注意先中止自己的应用程序,使关闭过程更显平顺。当然,您的进程必须有足够的优先权,否则也不能执行这种操作.
下图为我们对程序界面的修改.其中我们主要添加了一个frame1 ,两个单选框( Option1和Option2 ) , 三个文本框( text1 , text2 , text3 ) , 三个标签( label1 , label2 , label3 ) 以及一个按钮Command1.其中两个单选框( Option1和Option2 ) ,可以通过选择其中的一个,来确定究竟要使用那种功能. 三个文本框( text1 , text2 , text3 )来接受设定的时间,之后点击按钮Command1来应用.
下面是添加和修改的代码:
‘ = = = = = = = = = = = = = = = = = = = =
‘下面的为新添加的
‘ = = = = = = = = = = = = = = = = = = = =
Dim guanji As Boolean
Dim sheshi As Integer
Dim shefen As Integer
Dim shemiao As Integer
Private Sub Command1 _ Click ( )
If Text1 . Text = "" Or Text2 . Text = "" Or Text3 . Text Then
MsgBox "请填完整"
End If
If Option1.Value = True Then
guanji = True
end if
sheshi = Text1 . Text
shefen = Text2 . Text
shemiao = Text3 . Text
End Sub
‘ = = = = = = = = = = = = = = = = = = = = = =
‘ 下面语句中,添加了一部分,有标示
‘ = = = = = = = = = = = = = = = = = = = = = =
Private Sub Timer1 _ Timer ( )
miao = Second ( Time )
miao = 60 – miao
fen = Minute ( Time )
fen = 60 - fen
shi = Hour ( Time )
If shi > = 12 Then ‘因为一天之内时针要走二十四个钟头,也就是要走两圈,所以将下午和晚上的时间减去十二,就可以确定时针准确的位置
shi = shi - 12
End If
shi = 12 - shi
miao = xianshimiao ( maio )
fen = xianshifen ( fen )
shi = xianshishi ( shi )
‘ = = = = = = = = = = = = = = = = = = = =
‘ 下面几句为新添加的
‘ = = = = = = = = = = = = = = = = = = = =
if sheshi = shi and shefen = fen and shemiao = miao then
if guanji = true then
call ExitWindowsEx ( EWX_SHUTDOWN , 0 )
else
Msgbox “ 您设定的时间已到 ”
End if
If fen = 0 and miao = 0 then ‘如果分针和秒针都为零,这位整点,根据时针的数报时
Select case shi
MMControl1 . FileName = App . Path & “ 0.wav ” ‘选择要打开的文件
MMControl1 . Commond = “ Open ” ‘打开所选择的文件
MMControl1 . Commond = “ Play ” ‘播放所选择的文件
Case 1 ‘ 一点,1.wav报时一点,以下依次类推
MMControl1 . FileName = App . Path & “ 1.wav ” ‘选择要打开的文件
MMControl1 . Commond = “ Open ” ‘打开所选择的文件
MMControl1 . Commond = “ Play ” ‘播放所选择的文件
Case 2
MMControl1 . FileName = App . Path & “ 2.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 3
MMControl1 . FileName = App . Path & “ 3.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 4
MMControl1 . FileName = App . Path & “ 4.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 5
MMControl1 . FileName = App . Path & “ 5.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 6
MMControl1 . FileName = App . Path & “ 6.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 7
MMControl1 . FileName = App . Path & “ 7.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 8
MMControl1 . FileName = App . Path & “ 8.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 9
MMControl1 . FileName = App . Path & “ 9.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 10
MMControl1 . FileName = App . Path & “ 10.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
Case 11
MMControl1 . FileName = App . Path & “ 11.wav ”
MMControl1 . Commond = “ Open ”
MMControl1 . Commond = “ Play ”
End Select
MMControl1.Commond = “ Close ”
End Sub
我们终于写出了一个完整的钟表程序,其中很多部分内容,大家都是熟悉的,但怎样将这些知识应用的实际的开发中呢?很现实的问题,希望本篇能让你对编程能够从新思考,深入理解.