Option Strict Off
Option Explicit On
Imports Microsoft.VisualBasic.Compatibility
Public Class ClsWaitableTimer
Private Structure FILETIME
Dim dwLowDateTime As Integer
Dim dwHighDateTime As Integer
End Structure
Private Const WAIT_ABANDONED As Integer = &H80
Private Const WAIT_ABANDONED_0 As Integer = &H80
Private Const WAIT_FAILED As Integer = -1
Private Const WAIT_IO_COMPLETION As Integer = &HC0
Private Const WAIT_OBJECT_0 As Integer = 0
Private Const WAIT_OBJECT_1 As Integer = 1
Private Const WAIT_TIMEOUT As Integer = &H102
Private Const INFINITE As Short = &HFFFFS
Private Const ERROR_ALREADY_EXISTS As Short = 183
Private Const QS_HOTKEY As Integer = &H80S
Private Const QS_KEY As Integer = &H1S
Private Const QS_MOUSEBUTTON As Integer = &H4S
Private Const QS_MOUSEMOVE As Integer = &H2S
Private Const QS_PAINT As Integer = &H20S
Private Const QS_POSTMESSAGE As Integer = &H8S
Private Const QS_SENDMESSAGE As Integer = &H40S
Private Const QS_TIMER As Integer = &H10S
Private Const QS_MOUSE As Integer = (QS_MOUSEMOVE Or QS_MOUSEBUTTON)
Private Const QS_INPUT As Integer = (QS_MOUSE Or QS_KEY)
Private Const QS_ALLEVENTS As Integer = (QS_INPUT Or QS_POSTMESSAGE Or QS_TIMER Or QS_PAINT Or QS_HOTKEY)
Private Const QS_ALLINPUT As Integer = (QS_SENDMESSAGE Or QS_PAINT Or QS_TIMER Or QS_POSTMESSAGE Or QS_MOUSEBUTTON Or QS_MOUSEMOVE Or QS_HOTKEY Or QS_KEY)
Private Const UNITS As Double = 4294967296.0#
Private Const MAX_LONG As Double = -2147483648.0#
Private Declare Function CreateWaitableTimer Lib "kernel32" Alias "CreateWaitableTimerA" (ByVal lpSemaphoreAttributes As Integer, ByVal bManualReset As Integer, ByVal lpName As String) As Integer
Private Declare Function OpenWaitableTimer Lib "kernel32" Alias "OpenWaitableTimerA" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal lpName As String) As Integer
'UPGRADE_WARNING: 结构 FILETIME 可能要求封送处理属性作为此声明语句中的参数传递。 单击以获得更多信息:“ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="vbup1050"”
Private Declare Function SetWaitableTimer Lib "kernel32" (ByVal hTimer As Integer, ByRef lpDueTime As FILETIME, ByVal lPeriod As Integer, ByVal pfnCompletionRoutine As Integer, ByVal lpArgToCompletionRoutine As Integer, ByVal fResume As Integer) As Integer
Private Declare Function CancelWaitableTimer Lib "kernel32" (ByVal hTimer As Integer) As Object
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Integer, ByVal dwMilliseconds As Integer) As Integer
Private Declare Function MsgWaitForMultipleObjects Lib "user32" (ByVal nCount As Integer, ByRef pHandles As Integer, ByVal fWaitAll As Integer, ByVal dwMilliseconds As Integer, ByVal dwWakeMask As Integer) As Integer
Private mlTimer As Integer
Public GWNO As String
Public aaa As String
'UPGRADE_NOTE: Class_Terminate 已升级到 Class_Terminate_Renamed。 单击以获得更多信息:“ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="vbup1061"”
Private Sub Class_Terminate_Renamed()
On Error Resume Next
If mlTimer <> 0 Then CloseHandle(mlTimer)
End Sub
Protected Overrides Sub Finalize()
Class_Terminate_Renamed()
MyBase.Finalize()
End Sub
Public Sub Wait(ByRef MilliSeconds As Integer)
On Error GoTo ErrHandler
Dim ft As FILETIME
Dim lBusy As Integer
Dim lRet As Integer
Dim dblDelay As Double
Dim dblDelayLow As Double
aaa = Trim(GWNO) & "Timer" & VB6.Format(Now, "NNSS")
'mlTimer = CreateWaitableTimer(0, True, VB6.GetEXEName() & "Timer" & VB6.Format(Now, "NNSS"))
mlTimer = CreateWaitableTimer(0, True, Trim(GWNO) & "Timer" & VB6.Format(Now, "NNSS"))
If Err.LastDllError <> ERROR_ALREADY_EXISTS Then
ft.dwLowDateTime = -1
ft.dwHighDateTime = -1
lRet = SetWaitableTimer(mlTimer, ft, 0, 0, 0, 0)
End If
' Convert the Units to nanoseconds.
dblDelay = CDbl(MilliSeconds) * 10000.0#
' By setting the high/low time to a negative number, it tells
' the Wait (in SetWaitableTimer) to use an offset time as
' opposed to a hardcoded time. If it were positive, it would
' try to convert the value to GMT.
ft.dwHighDateTime = -CInt(dblDelay / UNITS) - 1
dblDelayLow = -UNITS * (dblDelay / UNITS - Fix(CShort(CStr(dblDelay / UNITS))))
If dblDelayLow < MAX_LONG Then dblDelayLow = UNITS + dblDelayLow
ft.dwLowDateTime = CInt(dblDelayLow)
lRet = SetWaitableTimer(mlTimer, ft, 0, 0, 0, False)
Do
' QS_ALLINPUT means that MsgWaitForMultipleObjects will
' return every time the thread in which it is running gets
' a message. If you wanted to handle messages in here you could,
' but by calling Doevents you are letting DefWindowProc
' do its normal windows message handling---Like DDE, etc.
lBusy = MsgWaitForMultipleObjects(1, mlTimer, False, INFINITE, QS_ALLINPUT)
System.Windows.Forms.Application.DoEvents()
Loop Until lBusy = WAIT_OBJECT_0
' Close the handles when you are done with them.
CloseHandle(mlTimer)
mlTimer = 0
Exit Sub
ErrHandler:
Err.Raise(Err.Number, Err.Source, "[clsWaitableTimer.Wait]" & Err.Description)
End Sub
End Class
可以精确到us。
Dim sw As New Stopwatch
sw.Start()
Dim LngA As Long = sw.ElapsedTicks
Do
If sw.ElapsedMilliseconds - LngA >= 12222 Then
LngA = sw.ElapsedTicks
End If
Loop
sw.Stop()