How to use Callback with a Class function into SetWinEventHook? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
logan9
Posts: 33
Joined: 22 Feb 2022, 12:48

How to use Callback with a Class function into SetWinEventHook?

Post by logan9 » 10 Aug 2022, 18:22

The script below works 'correctly' as long the callback function WinProcCallback is outside of a class
this works:

Code: Select all

hook1 := Hook.SetWinEventHook("EVENT_SYSTEM_FOREGROUND", "EVENT_SYSTEM_FOREGROUND", 0
, "WinProcCallback"     		; <------  the function is not inside of a class
, 0, 0, "WINEVENT_OUTOFCONTEXT")
return

When i try to use the same function, but now the function is inside of the class Hook.WinProcCallback
something goes wrong and the value of hWnd inside of Hook.WinProcCallback is always 0.

Code: Select all

hook1 := Hook.SetWinEventHook("EVENT_SYSTEM_FOREGROUND", "EVENT_SYSTEM_FOREGROUND", 0
, "Hook.WinProcCallback" 		; <------ same function but now inside of a class, the script doesn't work properly
, 0, 0, "WINEVENT_OUTOFCONTEXT")
return


Code: Select all

WinProcCallback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) { 

   WinGetClass, WinClass, ahk_id %hWnd%
   FileAppend, hWnd: %hWnd% WinClass: %WinClass% `n,*

}

   
Class Hook {

   SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwflags) {
      
      static EVENT_SYSTEM_FOREGROUND := 0x0003

      ; eventMin/eventMax check
      If ( !%eventMin% || !%eventMax% )
         Return 0

      nCheck := DllCall( "CoInitialize", Ptr,0       )
      DllCall( "SetLastError", UInt,nCheck ) ; SetLastError in case of success/error
               
      If ( nCheck == E_INVALIDARG || nCheck == E_OUTOFMEMORY ||  nCheck == E_UNEXPECTED )
         Return -1
      
      If ( isFunc(lpfnWinEventProc) )
         lpfnWinEventProc := RegisterCallback(lpfnWinEventProc)
         
      hWinEventHook := DllCall( "SetWinEventHook", UInt, %eventMin%, UInt, %eventMax%, Ptr,hmodWinEventProc, Ptr,lpfnWinEventProc, UInt,idProcess, UInt,idThread, UInt, dwflags )
      
      Return (hWinEventHook) ? hWinEventHook : 0
      
   }



   WinProcCallback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {

      ; hWnd is returned wrong being always 0 			; <---------------------
      WinGetClass, WinClass, ahk_id %hWnd%
      FileAppend, hWnd: %hWnd% WinClass: %WinClass% `n,*
 
   }

}

Am i doing something wrong in the callback or what?

swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: How to use Callback with a Class function into SetWinEventHook?

Post by swagfag » 11 Aug 2022, 18:14

Code: Select all

class MyClass
{
	MyInstanceVar := 123

	MyInstanceMethod() {
		this := Object(A_EventInfo) ; weak-ref, careful how u manage lifetimes
		MsgBox % this.MyInstanceVar
	}
}

InstanceOfMyClass := new MyClass
DllCall(RegisterCallback(MyClass.MyInstanceMethod, , , &InstanceOfMyClass))

User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: How to use Callback with a Class function into SetWinEventHook?  Topic is solved

Post by FanaticGuru » 11 Aug 2022, 18:58

logan9 wrote:
10 Aug 2022, 18:22
The script below works 'correctly' as long the callback function WinProcCallback is outside of a class
this works:

Code: Select all

hook1 := Hook.SetWinEventHook("EVENT_SYSTEM_FOREGROUND", "EVENT_SYSTEM_FOREGROUND", 0
, "Hook.WinProcCallback" 		; <------ same function but now inside of a class, the script doesn't work properly
, 0, 0, "WINEVENT_OUTOFCONTEXT")
return

Code: Select all

   
Class Hook {

'
'
'

   WinProcCallback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {

      ; hWnd is returned wrong being always 0 			; <---------------------
      WinGetClass, WinClass, ahk_id %hWnd%
      FileAppend, hWnd: %hWnd% WinClass: %WinClass% `n,*
 
   }

}

Am i doing something wrong in the callback or what?

Does not call the class method or does not have the parameters you are expecting?

A message call as a method will not have these parameters: WinProcCallback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)

It will have these parameters:

Code: Select all

	Message(event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)  ; 'Private Method 
		{
			hWinEventHook := this ; this' is hidden param1 because method is called as func
When parameters are passed to a method by a callback, the first parameter goes into this.

ObjBindMethod can also be used sometimes to get the result desired.

A lot of this is sorted out and can be seen in my [Class] WinHook at viewtopic.php?t=59149

It is the primary reason I wrote the class is that Shell Hooks and Event Hooks can be pretty complicated to get right. Then you are just left with all the complications of watching for the right events and using the information.

FG
Last edited by FanaticGuru on 11 Aug 2022, 19:10, edited 1 time in total.
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

logan9
Posts: 33
Joined: 22 Feb 2022, 12:48

Re: How to use Callback with a Class function into SetWinEventHook?

Post by logan9 » 11 Aug 2022, 19:02

Thank you, i didnt know the first parameter come as 'this'

Post Reply

Return to “Ask for Help (v1)”