Page 1 of 1

OnResume() - action when resume from sleep/standby/lock/etc

Posted: 05 Sep 2017, 20:50
by gwarble
this can probably be improved upon by some of you geniuses, but here's a tidy/simple function for running a subroutine when resuming from sleep, standby or hibernate, or unlocking or logging on while running. Lots more options could be added and full wrapping of WM_PowerBroadcast and WM_WTSSession_Change would be better, but in my case this is all I need.

Use:
OnResume( Label [, Delay ] )
where
Label = Subroutine to run
Delay = delay in ms

Code: Select all

OnResume(Label,Delay=200,Msg="") {
 static Init, Label_, Delay_
 If !Init ;first time called
 {
  DllCall("RegisterSuspendResumeNotification", "ptr", A_ScriptHwnd, "uint", 0)
  DllCall( "Wtsapi32.dll\WTSRegisterSessionNotification", "uint", A_ScriptHwnd, "uint", 1 )
  OnMessage(0x218, "OnResume") ;WM_POWERBROADCAST
  OnMessage(0x2B1, "OnResume") ;WM_WTSSESSION_CHANGE
  Label_ := Label
  Delay_ := Delay
 }
 Init := 1
 If !IsLabel(Label_)
  Return
 If (Msg = 0x218)
  If (Label=0x7) OR (Label=0x8) OR (Label=0x18) ; PBT_APMRESUMESUSPEND=0x7, PBT_APMRESUMESTANDBY=0x8, PBT_APMRESUMEAUTOMATIC=0x18
   SetTimer, %Label_%, -%Delay_%
 If (Msg = 0x2B1)
  If (Label=0x8) OR (Label=0x5) ; UNLOCK=0x8,LOGON=0x5
   SetTimer, %Label_%, -%Delay_% 
}
feedback appreciated
enjoy
- gwarble

Re: OnResume() - action when resume from sleep/standby/lock/etc

Posted: 06 Sep 2017, 01:53
by Helgef
Awesome gwarble :thumbup:
I tested it when unlocking, works perfect!
I might adapt it for v2 and change it to call a function instead of label, do you mind if I post that version here, in case someone else wants it for v2?

Cheers and thanks for sharing.

Edit: RegisterSuspendResumeNotification is windows 8 or newer. v2 gives the error, not v1.
Edit:
gwarble wrote: Please do...
Ok, this was my first attempt, only tested on the example. I check for OS >= win 8, and omit the RegisterSuspendResumeNotification call if needed.
Mini docs:
  • fn, func or boundfunc to be called on any resume event. fn is passed an event array describing the event. Eg [0x2B1, 0x8] on unlock
  • delay, delay in ms before fn is called after the event
  • Msg, internal use, omit
  • hwnd, pass a negative value if you want to update fn and delay. Else omit.

Code: Select all

; Note, the hotkey #l locks the computer.
; Example, show time locked when unlocking computer. 
#l::onResume(func("unlocked").bind(A_TickCount),1500,,-1)
unlocked(t, event){ ; iPhilip, https://autohotkey.com/boards/viewtopic.php?p=169634#p169634
	static eventNames:={ 0x218:{"":"WM_POWERBROADCAST",0x7:"PBT_APMRESUMESUSPEND",0x8:"PBT_APMRESUMESTANDBY",0x18:"PBT_APMRESUMEAUTOMATIC"}
						,0x2B1:{"":"WM_WTSSESSION_CHANGE",0x5:"LOGON",0x8:"UNLOCK"}}
	msgbox("Unlocked after " round(((A_TickCount-t) / 1000),2) "s.`nEvent: " eventNames[event.1][""] " : " eventNames[event.1][event.2] ".")
}

OnResume(fn,Delay:=200,Msg:="",hwnd:=0) {
	; Specify hwnd < 0 to change the notification function. (not needed on first call)
	static Init, Func_, Delay_
	local tf
	If !Init { ;first time called
		if regexreplace(A_OSVersion, "(\d\.\d).*","$1") >= 6.2
			DllCall("RegisterSuspendResumeNotification", "ptr", A_ScriptHwnd, "uint", 0)
		DllCall("Wtsapi32.dll\WTSRegisterSessionNotification", "uint", A_ScriptHwnd, "uint", 1 )
		OnMessage(0x218, "OnResume") ;WM_POWERBROADCAST
		OnMessage(0x2B1, "OnResume") ;WM_WTSSESSION_CHANGE
	}
	if !Init || hwnd<0 {
		If type(fn) != "func" && type(fn) != "BoundFunc"
			Return msgbox("invalid function")
		Func_ := fn
		Delay_ := Delay
		Init := 1
		return
	}
	If fn==1
		return Func_.call(msg)
	If (Msg = 0x218)
		If (fn=0x7) || (fn=0x8) || (fn=0x18) ; PBT_APMRESUMESUSPEND=0x7, PBT_APMRESUMESTANDBY=0x8, PBT_APMRESUMEAUTOMATIC=0x18
			tf:=func("OnResume").bind(1,0,[msg, fn]), SetTimer(tf, -Delay_)
	If (Msg = 0x2B1)
		If (fn=0x8) || (fn=0x5)					; UNLOCK=0x8,LOGON=0x5
			tf:=func("OnResume").bind(1,0,[msg, fn]), SetTimer(tf, -Delay_)
}

Re: OnResume() - action when resume from sleep/standby/lock/etc

Posted: 06 Sep 2017, 02:25
by jNizM
An example for WM_WTSSESSION_CHANGE (GitHub)

Re: OnResume() - action when resume from sleep/standby/lock/etc

Posted: 06 Sep 2017, 02:53
by gwarble
Thanks

Please do... I mainly wanted a nice streamlined function, a full wrapper for all the power stuff would be useful, but more than i need so low priority...

Function instead of label is a better idea, i'd probably implement it with a fallback of label so you could use either

I didn't notice any problem calling RegisterSuspendResumeNotification in XP or Win7, but we could make it conditional on those os's if its a problem

Re: OnResume() - action when resume from sleep/standby/lock/etc

Posted: 06 Sep 2017, 12:42
by Helgef
I updated my first post with a version for ahk v2
gwarble wrote: Please do... I mainly wanted a nice streamlined function, a full wrapper for all the power stuff would be useful, but more than i need so low priority...
We are on the same page here. If it was just a little bit more required coding, I'd do it another way do. I find this sort of dual-purpose functions both repulsive and fun to make :lol:
gwarble wrote: I didn't notice any problem calling RegisterSuspendResumeNotification in XP or Win7, but we could make it conditional on those os's if its a problem
AHK v1 will happily silently fail the dllcall, if you check errorlevel, you will find it to be -4,
DllCall wrote: -4: The specified function could not be found inside the DLL.
AHK v2, will conveniently throw an error. :thumbup:

Cheers.

Re: OnResume() - action when resume from sleep/standby/lock/etc

Posted: 09 Sep 2017, 13:37
by iPhilip
For those using AHK v1 and wanting to use a function instead of a label, I modified Helgef's version as follows:

Code: Select all

; Note, the hotkey #l locks the computer.
; Example, show time locked when unlocking computer. 
#l::onResume(func("unlocked").bind(A_TickCount),1500,,-1)
unlocked(t, event){
   static eventNames:={0x218:{"":"WM_POWERBROADCAST",0x7:"PBT_APMRESUMESUSPEND",0x8:"PBT_APMRESUMESTANDBY",0x18:"PBT_APMRESUMEAUTOMATIC"}
                     , 0x2B1:{"":"WM_WTSSESSION_CHANGE",0x5:"LOGON",0x8:"UNLOCK"}}
   msgbox % "Unlocked after " ((A_TickCount-t) / 1000) "s.`nEvent: " eventNames[event.1][""] " : " eventNames[event.1][event.2] "."
}

OnResume(fn,Delay:=200,Msg:="",hwnd:=0) {
   ; Specify hwnd < 0 to change the notification function. (not needed on first call)
   static Init, Func_, Delay_
   local tf
   If !Init { ;first time called
      if regexreplace(GetOSVersion(), "(\d\.\d).*","$1") >= 6.2
         DllCall("RegisterSuspendResumeNotification", "ptr", A_ScriptHwnd, "uint", 0)
      DllCall("Wtsapi32.dll\WTSRegisterSessionNotification", "uint", A_ScriptHwnd, "uint", 1 )
      OnMessage(0x218, "OnResume") ;WM_POWERBROADCAST
      OnMessage(0x2B1, "OnResume") ;WM_WTSSESSION_CHANGE
   }
   if !Init || hwnd<0 {
      If !IsFunc(fn) && !IsBoundFunc(fn) {
         MsgBox, invalid function
         Return
      }
      Func_ := fn
      Delay_ := Delay
      Init := 1
      return
   }
   If (fn==1)
      return Func_.call(msg)
   If (Msg = 0x218)
      If (fn=0x7) || (fn=0x8) || (fn=0x18) { ; PBT_APMRESUMESUSPEND=0x7, PBT_APMRESUMESTANDBY=0x8, PBT_APMRESUMEAUTOMATIC=0x18
         tf:=func("OnResume").bind(1,0,[msg, fn])
         SetTimer, % tf, -%Delay_%
      }
   If (Msg = 0x2B1)
      If (fn=0x8) || (fn=0x5) {               ; UNLOCK=0x8,LOGON=0x5
         tf:=func("OnResume").bind(1,0,[msg, fn])
         SetTimer, % tf, -%Delay_%
      }
}

; https://autohotkey.com/boards/viewtopic.php?p=40448#p40448

IsBoundFunc(obj) {
   static dummy := Func("Abs").Bind(1) ; dummy BoundFunc object
   return NumGet(&obj) == NumGet(&dummy)
}

; https://autohotkey.com/boards/viewtopic.php?p=19706#p19706

GetOSVersion() {
   Return ((M := (B := DllCall("Kernel32.dll\GetVersion")) & 0xFFFF) & 0xFF) "." (M >> 8) "." (B >> 16)
}
Cheers!

Re: OnResume() - action when resume from sleep/standby/lock/etc

Posted: 09 Sep 2017, 16:07
by Helgef
@iPhilip, cheers! :wave: :thumbup:
Just note, A_OSVersion has changed in v2, v1 gives a string like win_7, while v2 gives major.minor.build.
iPhilip wrote:

Code: Select all

unlocked(t, event){
   static eventNames:={0x218:{"":"WM_POWERBROADCAST",0x7:"PBT_APMRESUMESUSPEND",0x8:"PBT_APMRESUMESTANDBY",0x18:"PBT_APMRESUMEAUTOMATIC"}
                     , 0x2B1:{"":"WM_WTSSESSION_CHANGE",0x5:"LOGON",0x8:"UNLOCK"}}
   msgbox % "Unlocked after " ((A_TickCount-t) / 1000) "s.`nEvent: " eventNames[event.1][""] " : " eventNames[event.1][event.2] "."
}
I'll take it! :)

Re: OnResume() - action when resume from sleep/standby/lock/etc

Posted: 09 Sep 2017, 19:42
by iPhilip
Hi Helgef,

Thank you for catching that! I updated the above post with a function from jNizM that gives the OS version as major.minor.build. :)