我认为不可能在实例本身(即 via Me
)中调用方法,因为调用计时器时上下文会丢失。
不过,您可以使用全局变量(尽管这很讨厌)。问题在于,如果您有同一个类的多个实例,则每个实例都需要一个全局变量,并且代码需要知道要调用哪个变量。
但是,有一种解决方法 - 使用数组或字典作为单个全局对象,然后使用名称或 id 从该集合中标识您的实例。
现在,当您使用计时器时,调用类外部的方法,将实例的标识符作为值传递。您调用的方法可以在您的集合中查找此 id,返回您的实例,然后可以在该实例上调用相关方法。
有点破解,但它有效 - 玩一下下面的演示 hta 应用程序,看看它的实际效果。
搜索字符串'!Important
以查看代码的关键位。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="text/vbs" language="vbscript">
option explicit
dim dummies '!Important - this is the global variable holding all your instances
sub CreateDummyInstances()
dim dum
set dummies = CreateObject("Scripting.Dictionary")
set dum = (new Dummy)("Makaveli84", 5000)
set dum = (new Dummy)("JohnLBevan", 7000)
set dum = (new Dummy)("Ekkehard.Horner", 10000)
set dum = nothing
end sub
class Dummy
private m_name
private m_timeoutMilSec
private m_timerOn
private m_timerRunningLock
private sub Class_Initialize
m_timerOn = false
m_timerRunningLock = false
end sub
public default function Dummy(name, timeoutMilSec)
m_name = name
m_timeoutMilSec = timeoutMilSec
dummies.add name, me '!Important - add this new instance to our collection
CreateButton
set Dummy = me
end function
public property Get Name
Name = m_name
end property
public property Get IsTimerOn
IsTimerOn = m_timerOn
end property
public sub BeginTimer()
m_timerOn = true
if not m_timerRunningLock then 'avoid creating two threads if an off-on occurs within a single timer wait
TimerLoop
end if
end sub
public sub EndTimer()
m_timerOn = false
end sub
public sub TimerLoop()
if m_timerOn then 'get out of jail free (altered by separate thread)
m_timerRunningLock = true
PerformSomeAction
'this doesn't work because Me loses its context when called by the timer
'window.setTimeout "Me.TimerLoop", m_timeoutMilSec, "VBScript"
'so instead we pass a name / id for this object as a parameter to an external function
'and have that lookup this instance and externally call the method we wanted to call
window.setTimeout "TheFunkyTrick(""" & m_name & """)", m_timeoutMilSec, "VBScript" '!Important - call the external function
else
m_timerRunningLock = false
end if
end sub
private sub CreateButton()
dim p
dim button
set p = document.createElement("p")
set button = document.createElement("button")
button.id = "btnStart" & m_name
button.innerText = "Start " & m_name
AddClickEventHandler button, "StartTimer"
p.appendChild button
set button = document.createElement("button")
button.id = "btnStop" & m_name
button.innerText = "Stop " & m_name
AddClickEventHandler button, "StopTimer"
p.appendChild button
divButtons.appendChild p
set button = Nothing
set p = Nothing
end sub
private sub AddClickEventHandler(objButton, strFunctionName)
dim fun
set fun = getRef(strFunctionName)
call objButton.attachEvent("onclick", fun)
set fun = Nothing
end sub
sub PerformSomeAction
msgbox "Hello from " & m_name & ". I show up every " & cstr(cint(m_timeoutMilSec/1000)) & " seconds, until stopped."
end sub
end class
function vbInit()
CreateDummyInstances
end function
function GetDummy(name)
if dummies.exists(name) then
set GetDummy = dummies(name) '!Important - get desired instance from the collection (assuming it exists)
else
msgbox "name not found: " & name
set GetDummy = nothing 'the way I've coded stuff below this would cause an exception (i.e. since I've not bothered to check if it's nothing) - but as this is a demo that's fine
end if
end function
function GetNameFromButtonEvent(objEvent, boilerplate)
GetNameFromButtonEvent = Right(objEvent.srcElement.Id, len(objEvent.srcElement.Id) - len(boilerplate))
end function
sub StartTimer(objEvent)
dim name
name = GetNameFromButtonEvent(objEvent, "btnStart")
GetDummy(name).BeginTimer
end sub
sub StopTimer(objEvent)
dim name
name = GetNameFromButtonEvent(objEvent, "btnStop")
GetDummy(name).EndTimer
end sub
sub TheFunkyTrick(name) '!Important - call the method on the relevant instance
GetDummy(name).TimerLoop
end sub
</script>
<HTA:APPLICATION
ApplicationName="Stack Overflow VBScript Class Timer Demo"
Caption="Yes"
icon="img/favicon.ico"
Scroll="no"
SingleInstance="yes"
WindowState="normal"
ShowInTaskbar="Yes"
SysMenu="Yes"
MaximizeButton="No"
ShowInTaskbar="Yes"
MinimizeButton="No"
Navigable="No"
Border="Thin"
BORDERSTYLE="Complex"
INNERBORDER="No"
/>
<title>Stack Overflow VBScript Class Timer Demo</title>
</head>
<body onload="vbInit()" language="vbscript">
<h1>Demo</h1>
<div id="divButtons"></div>
</body>
</html>