Class 制作HTA';s setTimeout或setInterval调用VBScript类中的子函数/函数
好吧,标题说明了一切。我有一个带有VBS类的HTA,我试图用另一个类sub作为其“函数”参数调用setInterval,但我得到了一个“类型不匹配”错误。 这可以以任何直接或变通的黑客形式完成吗?我能想到的唯一一件事就是在类外使用“argument”函数,但这种方法首先就违背了类的目的。。。 救命啊 编辑(示例代码): 基于我的想法,setInterval将把“function”字符串传递给GetRef(),但它的工作方式更像eval:Class 制作HTA';s setTimeout或setInterval调用VBScript类中的子函数/函数,class,vbscript,settimeout,setinterval,hta,Class,Vbscript,Settimeout,Setinterval,Hta,好吧,标题说明了一切。我有一个带有VBS类的HTA,我试图用另一个类sub作为其“函数”参数调用setInterval,但我得到了一个“类型不匹配”错误。 这可以以任何直接或变通的黑客形式完成吗?我能想到的唯一一件事就是在类外使用“argument”函数,但这种方法首先就违背了类的目的。。。 救命啊 编辑(示例代码): 基于我的想法,setInterval将把“function”字符串传递给GetRef(),但它的工作方式更像eval: <html> <head>
<html>
<head>
<Title>SetIntervalDemo</Title>
<hta:application id="SetIntervalDemo" scroll = "no">
<script type="text/vbscript">
Dim g_sp0
Sub sp0()
MsgBox "sp0 called"
ClearInterval g_sp0
End Sub
Sub sisp0()
g_sp0 = SetInterval(GetRef("sp0"), 1000)
' g_sp0 = SetInterval("mp0", 1000) <---- Type Mismatch
End Sub
Dim g_sp1
Sub sp1(x)
MsgBox "sp1 called: " & x
ClearInterval g_sp1
End Sub
Sub sisp1()
g_sp1 = SetInterval("sp1(4711 + g_sp1)", 1000)
End Sub
Dim g_mp0_a
Dim g_o_a
Dim g_mp0_b
Dim g_o_b
Sub simp0()
Set g_o_a = New cC : g_o_a.m_sName = "Alpha"
Set g_o_b = New cC : g_o_b.m_sName = "Beta"
g_mp0_a = SetInterval("g_o_a.mp0", 1000)
g_mp0_b = SetInterval("g_o_b.mp0", 1000)
End Sub
Class cC
Public m_sName
Public Sub mp0()
MsgBox m_sName & ".mp0 called"
ClearInterval g_mp0_a
ClearInterval g_mp0_b
End Sub
End Class
</script>
</head>
<body>
<input type="button" value="sp0" onclick="sisp0" />
<input type="button" value="sp1" onclick="sisp1" />
<input type="button" value="mp0" onclick="simp0" />
</body>
</html>
SetIntervalDemo
暗g_sp0
子sp0()
MsgBox“调用sp0”
间隙g_sp0
端接头
亚组sisp0()
g_sp0=设定间隔(GetRef(“sp0”),1000)
“g_sp0=SetInterval(“mp0”,1000)基于我的想法,SetInterval将把“函数”字符串传递给GetRef(),但它的工作方式似乎更像eval:
<html>
<head>
<Title>SetIntervalDemo</Title>
<hta:application id="SetIntervalDemo" scroll = "no">
<script type="text/vbscript">
Dim g_sp0
Sub sp0()
MsgBox "sp0 called"
ClearInterval g_sp0
End Sub
Sub sisp0()
g_sp0 = SetInterval(GetRef("sp0"), 1000)
' g_sp0 = SetInterval("mp0", 1000) <---- Type Mismatch
End Sub
Dim g_sp1
Sub sp1(x)
MsgBox "sp1 called: " & x
ClearInterval g_sp1
End Sub
Sub sisp1()
g_sp1 = SetInterval("sp1(4711 + g_sp1)", 1000)
End Sub
Dim g_mp0_a
Dim g_o_a
Dim g_mp0_b
Dim g_o_b
Sub simp0()
Set g_o_a = New cC : g_o_a.m_sName = "Alpha"
Set g_o_b = New cC : g_o_b.m_sName = "Beta"
g_mp0_a = SetInterval("g_o_a.mp0", 1000)
g_mp0_b = SetInterval("g_o_b.mp0", 1000)
End Sub
Class cC
Public m_sName
Public Sub mp0()
MsgBox m_sName & ".mp0 called"
ClearInterval g_mp0_a
ClearInterval g_mp0_b
End Sub
End Class
</script>
</head>
<body>
<input type="button" value="sp0" onclick="sisp0" />
<input type="button" value="sp1" onclick="sisp1" />
<input type="button" value="mp0" onclick="simp0" />
</body>
</html>
SetIntervalDemo
暗g_sp0
子sp0()
MsgBox“调用sp0”
间隙g_sp0
端接头
亚组sisp0()
g_sp0=设定间隔(GetRef(“sp0”),1000)
'g_sp0=SetInterval(“mp0”,1000)我认为不可能在实例本身中调用方法(即通过Me
),因为调用计时器时上下文丢失
您可以使用一个全局变量(尽管这很糟糕)。问题是,如果同一类有多个实例,那么每个实例都需要一个全局变量,代码需要知道调用哪个变量
但是,上面有一个解决方法-使用数组或字典作为单个全局对象,然后使用名称或id从该集合中标识实例
现在,当您使用计时器时,在类外调用一个方法,将实例的标识符作为值传递。您调用的方法可以在集合中查找此id,返回您的实例,然后可以调用该实例上的相关方法
有点黑客,但它的工作-有一个演示hta应用程序下面发挥看看它的行动
搜索字符串“!重要信息
查看代码的关键位
<!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>
选项显式
傻瓜!重要信息-这是保存所有实例的全局变量
子CreateDummyInstances()
暗哑
set dummies=CreateObject(“Scripting.Dictionary”)
设置dum=(新假人)(“Makaveli84”,5000)
设置dum=(新假人)(“约翰贝万”,7000)
设置dum=(新假人)(“Ekkehard.Horner”,10000)
设置dum=无
端接头
类虚拟
私人m_名称
私人m_timeoutMilSec
二等兵m_timerOn
专用定时锁
私有子类_初始化
m_timerOn=错误
m_timerRunningLock=错误
端接头
公共默认函数虚拟(名称,timeoutMilSec)
m_name=名称
m_timeoutMilSec=timeoutMilSec
傻瓜,加上名字,我!重要信息-将此新实例添加到我们的集合中
创建按钮
设置虚拟=我
端函数
公共属性获取名称
Name=m_Name
端属性
公共财产
IsTimerOn=m_timerOn
端属性
公共子起始者()
m_timerOn=真
如果不是m_timerRunningLock,则“如果在单个计时器等待中发生关闭-打开,则避免创建两个线程”
定时器环路
如果结束
端接头
公共子结束计时器()
m_timerOn=错误
端接头
公共子TimerLoop()
如果m_timerOn然后“自由出狱”(通过单独的线程更改)
m_timerRunningLock=真
表演动作
'这不起作用,因为当计时器调用Me时,Me会丢失其上下文
'window.setTimeout“Me.TimerLoop”、m_timeoutMilSec、“VBScript”
'因此,我们将此对象的名称/id作为参数传递给外部函数
'并将该查找用于此实例,并从外部调用我们想要调用的方法
window.setTimeout“TheFunkyTrick(“”&m_name&“”)”,m_timeoutMilSec,“VBScript”!要点-调用外部函数
其他的
m_timerRunningLock=错误
如果结束
端接头
私有子CreateButton()
暗p
暗按钮
set p=document.createElement(“p”)
设置按钮=document.createElement(“按钮”)
button.id=“btnStart”&m\u名称
button.innerText=“开始”&m\u名称
AddClickEventHandler按钮,“StartTimer”
p、 附加子按钮
设置按钮=document.createElement(“按钮”)
button.id=“btnStop”&m\u名称
button.innerText=“停止”&m\u名称
AddClickEventHandler按钮,“停止计时器”
p、 附加子按钮
divButtons.appendChild p
设置按钮=无
设置p=无
端接头
私有子AddClickEventHandler(对象按钮,strFunctionName)
暗淡的乐趣
set fun=getRef(strFunctionName)
Class My_Class
Private TimerID
Public Sub Sub1(param)
Dim x
x = DoSomeCalculations(param)
Dim cb
Set cb = New MyCallback
Set cb.Target = Me
cb.ParamValue = x
TimerID = window.setInterval(cb , 1000, "VBScript")
End Sub
' must be Public
Public Sub Sub2(param)
Dim y
y = DoSomeMoreCalculations
If param = y Then window.clearInterval(TimerID)
End Sub
End Class
Class MyCallback
Public Target
Public ParamValue
' must be Public and Default
Public Default Sub DoCall
Target.Sub2 ParamValue
End Sub
End Class