Try this, it is a modifed version of SetTimerF().
Code: Select all
Counter1 := new CounterClass()
Counter2 := new CounterClass()
return
F1::Counter1.Start()
F2::Counter1.Stop()
F3::Counter2.Start()
F4::Counter2.Stop()
Class CounterClass {
static Counter := 0
Count() {
this.Counter += 1
ToolTip, % this.Counter
}
Start() {
this.SetTimer(this.base.count,250)
}
Stop() {
this.SetTimer(this.base.count)
}
SetTimer( Function, Period=0, ParmObject=0, Priority=0 ) {
Static tmrs:=[] ; will hold timers that are currently running
If IsFunc( Function ) {
if IsObject(tmr:=tmrs[this]) ;destroy timer before creating a new one
ret := DllCall( "KillTimer", "UInt",0, "UInt", tmr.tmr)
, DllCall("GlobalFree", "UInt", tmr.CBA)
, ObjRemove(tmrs,this)
if (Period = 0 || Period = "off")
return ret ;Return as we want to turn off timer
; create object that will hold information for timer, it will be passed trough A_EventInfo when Timer is launched
tmr:=tmrs[this]:={func:Function,ref:this,Period:Period="on" ? 250 : Period,Priority:Priority
,OneTime:Period<0,params:IsObject(ParmObject)?ParmObject:[],Tick:A_TickCount}
,tmr.CBA := RegisterCallback(this.base.SetTimer,"F",4,&tmr)
return !!(tmr.tmr := DllCall("SetTimer", "UInt",0, "UInt",0, "UInt"
, (Period && Period!="On") ? Abs(Period) : (Period := 250)
, "UInt",tmr.CBA)) ;Create Timer and return true if a timer was created
, tmr.Tick:=A_TickCount
}
if IsObject(tmr := Object(A_EventInfo)) { ;A_Event holds object which contains timer information
DllCall("KillTimer", "UInt",0, "UInt",tmr.tmr) ;deactivate timer so it does not run again while we are processing the function
,tmr.tick:= ErrorLevel := A_TickCount ;update tick to launch function on time
,func:=tmr.func,%func%(tmr.ref,tmr.params*) ; call function
if (tmr.OneTime) ;One time timer, deactivate and delete it
return DllCall("GlobalFree", "UInt",tmr.CBA)
,ObjRemove(tmrs,tmr.ref?tmr.ref:tmr.func)
tmr.tmr := DllCall("SetTimer", "UInt",0, "UInt",0, "UInt" ;reset timer
,((A_TickCount-tmr.Tick) > tmr.Period) ? 0 : (tmr.Period-(A_TickCount-tmr.Tick)), "UInt",tmr.CBA)
}
}
}
Here is a Gui Example implementing 6 Timers.
I have also added __New to set timer period and control.
Note that each timer uses different settimer period.
Code: Select all
Gui,Add,Text,,Counter1 (Start=F1/Stop=F2):
Gui,Add,Edit,x+14 w40 ReadOnly,0
Counter1 := new CounterClass("Edit1")
Gui,Add,Text,xs,Counter2 (Start=F3/Stop=F4):
Gui,Add,Edit,x+14 w40 ReadOnly,0
Counter2 := new CounterClass("Edit2",150)
Gui,Add,Text,xs,Counter2 (Start=F5/Stop=F6):
Gui,Add,Edit,x+14 w40 ReadOnly,0
Counter3 := new CounterClass("Edit3",100)
Gui,Add,Text,xs,Counter2 (Start=F7/Stop=F8):
Gui,Add,Edit,x+14 w40 ReadOnly,0
Counter4 := new CounterClass("Edit4",50)
Gui,Add,Text,xs,Counter2 (Start=F9/Stop=F10):
Gui,Add,Edit,x+8 w40 ReadOnly,0
Counter5 := new CounterClass("Edit5",500)
Gui,Add,Text,xs,Counter2 (Start=F11/Stop=F12):
Gui,Add,Edit,x+2 w40 ReadOnly,0
Counter6 := new CounterClass("Edit6",1000)
Gui,Show
map:=[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12]
return
GuiClose:
ExitApp
F1::
F2::
F3::
F4::
F5::
F6::
F7::
F8::
F9::
F10::
F11::
F12::
c:=map[SubStr(A_ThisHotkey,2)]
Counter%c%[Mod(SubStr(A_ThisHotkey,2),2)?"Start":"Stop"]()
Return
Class CounterClass {
static Counter := 0, control := 0
__New(control,timer:=250){
this.control:=control
,this.timer := timer
}
Count() {
this.Counter += 1
GuiControl,,% this.control,% this.Counter
}
Start() {
this.SetTimer(this.base.count,this.timer)
}
Stop() {
this.SetTimer(this.base.count)
}
SetTimer( Function, Period=0, ParmObject=0, Priority=0 ) {
Static tmrs:=[] ; will hold timers that are currently running
If IsFunc( Function ) {
if IsObject(tmr:=tmrs[this]) ;destroy timer before creating a new one
ret := DllCall( "KillTimer", "UInt",0, "UInt", tmr.tmr)
, DllCall("GlobalFree", "UInt", tmr.CBA)
, ObjRemove(tmrs,this)
if (Period = 0 || Period = "off")
return ret ;Return as we want to turn off timer
; create object that will hold information for timer, it will be passed trough A_EventInfo when Timer is launched
tmr:=tmrs[this]:={func:Function,ref:this,Period:Period="on" ? 250 : Period,Priority:Priority
,OneTime:Period<0,params:IsObject(ParmObject)?ParmObject:[],Tick:A_TickCount}
,tmr.CBA := RegisterCallback(this.base.SetTimer,"F",4,&tmr)
return !!(tmr.tmr := DllCall("SetTimer", "UInt",0, "UInt",0, "UInt"
, (Period && Period!="On") ? Abs(Period) : (Period := 250)
, "UInt",tmr.CBA)) ;Create Timer and return true if a timer was created
, tmr.Tick:=A_TickCount
}
if IsObject(tmr := Object(A_EventInfo)) { ;A_Event holds object which contains timer information
DllCall("KillTimer", "UInt",0, "UInt",tmr.tmr) ;deactivate timer so it does not run again while we are processing the function
,tmr.tick:= ErrorLevel := A_TickCount ;update tick to launch function on time
,func:=tmr.func,%func%(tmr.ref,tmr.params*) ; call function
if (tmr.OneTime) ;One time timer, deactivate and delete it
return DllCall("GlobalFree", "UInt",tmr.CBA)
,ObjRemove(tmrs,tmr.ref?tmr.ref:tmr.func)
tmr.tmr := DllCall("SetTimer", "UInt",0, "UInt",0, "UInt" ;reset timer
,((A_TickCount-tmr.Tick) > tmr.Period) ? 0 : (tmr.Period-(A_TickCount-tmr.Tick)), "UInt",tmr.CBA)
}
}
}