Timer 类
Timer是非可视的Win32控件,以可编程间隔引发Timer事件。在设计时将其拖放到Form(或UserControl)上,将Interval设置为所需的毫秒周期,将Enabled设置为True,并处理Timer事件。计时器在运行时不可见——它们在设计器中仅显示为图标。
Private Sub Form_Load()
Timer1.Interval = 1000 ' 每秒触发一次
Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
lblClock.Caption = Format$(Now, "hh:mm:ss")
End Sub启动和停止
两个属性共同决定Timer事件是否触发:
任一属性都可以从Timer处理器内部切换——一次性计时器在首次计时后禁用自身:
Private Sub tmrStartup_Timer()
tmrStartup.Enabled = False ' 仅触发一次
LoadInitialData
End Sub为Interval赋负值会引发运行时错误380(无效的属性值)。
精度和分辨率
控件包装Win32的逐窗口计时器队列,运行在标准消息泵上。两个后果:
- 分辨率粗糙。 操作系统将计时器计时量化为系统时钟周期——桌面Windows上通常约15.6毫秒。短于此的间隔被静默向上取整。对于亚毫秒级定时,请直接使用多媒体计时器或
QueryPerformanceCounter。 - 高负载下可能跳过计时。 如果消息泵在计时时被阻塞,事件不会排队——运行时在消息泵恢复时传递单个Timer事件,而非每个错过的周期一个。处理器内部的长时间运行工作因此会延长下一个间隔而非产生积压。
对于周期性UI更新(时钟、进度动画、外部状态轮询),Timer是正确的工具。对于精确的挂钟定时、音频调度或在重CPU负载下必须跟上的任务,则不是。
控件数组
计时器控件数组允许一个处理器服务多个周期性任务,同时保持单一的共享代码路径。数组在设计时在第一个项上声明;后续项在运行时用Load添加、用Unload移除,与窗口控件完全相同。在共享的Timer处理器内部,Index标识哪个计时器触发了。
Private Sub tmrPoll_Timer(Index As Integer)
Select Case Index
Case 0: RefreshStatus
Case 1: PollPrinterQueue
Case 2: TrimLogFile
End Select
End SubIndex在不是控件数组一部分的计时器上读取时会引发运行时错误343(对象不是数组)。
属性
ControlType
标识此控件为计时器的只读ControlTypeConstants值。始终为vbTimer。
Enabled
计时器的主开关。当为False时,计时器处于休眠状态,无论Interval如何,Timer事件不会触发。Boolean,默认True。默认属性。
语法:object.Enabled [ = boolean ]
Index
当计时器是控件数组的一部分时,此实例在数组中从0开始的Long索引。运行时只读。在不是数组一部分的计时器上会引发运行时错误343(对象不是数组)。
Interval
Timer事件之间的周期,以毫秒为单位。Long,默认0。
语法:object.Interval [ = value ]
- value
- 给出毫秒间隔的非负Long。设置为
0停止事件触发。负值引发运行时错误380(无效的属性值)。
有效分辨率为操作系统时钟周期(桌面Windows上约15.6毫秒);更短的间隔被静默向上取整。参见精度和分辨率。
Left
设计器中计时器图标的水平位置,以容器的ScaleMode单位。Single。运行时值没有视觉效果——计时器不可见——但被保留以便设计器可以将图标放回原位。
Name
计时器在其父窗体上的唯一设计时名称。String,运行时只读。
Parent
对包含此计时器的Form(或UserControl)的引用。只读。
Tag
应用程序可用于将自定义数据与计时器关联的自由格式String。框架忽略。继承自基控件类。对控件数组很有用——例如保存轮询计时器负责的操作名称。
Top
设计器中计时器图标的垂直位置。Left的对应项;与Left一样,运行时没有视觉效果。
事件
Timer
当Enabled为True且Interval大于零时,每隔Interval毫秒引发。默认事件。
语法:object_Timer( )
对于控件数组一部分的计时器,处理器接收触发计时器的数组Index:
语法:object_Timer( Index As Integer )
事件通过正常的Win32消息泵传递——参见精度和分辨率了解其影响。