Page 1 of 1

[v1] v2's CallbackCreate function for AHK v1.

Posted: 05 Aug 2018, 09:32
by Helgef
Hello, this is an attempt to bring AHK v2's CallbackCreate function to AHK v1. In AHK v2, RegisterCallback is replaced by CallbackCreate.
For function documentation, please refer to the v2 docs for CallbackCreate.
Main highlights are,
  • Ability to pass a function object, compared to only function name for RegisterCallback.
  • "&" option to pass the address of the parameter list to the callback function, which doesn't need to be variadic, but can be.
  • Throws exception on failure.
Also available is the function CallbackFree, again see the v2 docs.

Using this function in v1 will make it easier for you to transition to v2 in the future, hopefully, all which will be required then is to remove #include callbackcreate.ahk from your script :thumbup:. For those interested in that sort of stuff, please also see jeeswg's functions.

All available at :arrow: github.

Cheers.

Re: [v1] v2's CallbackCreate function for AHK v1.

Posted: 05 Aug 2018, 12:16
by jeeswg
- Hello Helgef well done. :wave: :clap:
- Btw I might include this, or a version of it, in the next update of 'AHK v2 functions for AHK v1', if that's OK. Is that OK? Cheers.
commands as functions (AHK v2 functions for AHK v1) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 37&t=29689

Re: [v1] v2's CallbackCreate function for AHK v1.

Posted: 05 Aug 2018, 12:20
by Helgef
Hello. Yes, anyone is free to do whatever they like with this, in any place and form.

Cheers.

Re: [v1] v2's CallbackCreate function for AHK v1.

Posted: 17 Jan 2019, 19:23
by A_AhkUser
Thanks Helgef for this amazing and relevant function :thumbup: :salute:

I'm experimenting with the register callback examples from the documentation trying to understand how they works. Then I came up with the idea to implement the second one directly in the 'EventObj' example you provided @GuiSize Function inside Class Not Executing to see if I can this way create a GUISize Event obj. The fact that registercallback's functionName parameter does not support function objects brought me here: I remembered seeing this function a while ago.
The script below works but, for some reason, I cannot interact with the MsgBox which fires from the __Delete meta-method and adding a sleep simply crashes the script. Also, I don't know if, passing a func object, I need to take account of the 'this' hidden param for the ParamCount parameter (ParamCount + 1?). Sorry for these foolish questions, simply experimenting :headwall: - and enjoying trying your script :D

Code: Select all

#NoEnv
#SingleInstance force
SetWorkingDir % A_ScriptDir
SendMode, Input
CoordMode, ToolTip, Screen
#Warn
; Windows 8.1 64 bit - Autohotkey v1.1.30.01 32-bit Unicode

#Include %A_ScriptDir%\callbackcreate.ahk ; https://github.com/HelgeffegleH/AHK-misc./blob/master/functions/callbackcreate/callbackcreate.ahk

G := new GUI()
return
!i::CallbackFree(G._winProcNew)
Class GUI {

	__New() {
	
	static _winUserFunc := (A_PtrSize = 8) ? "SetWindowLongPtr" : "SetWindowLong"
	static GWL_WNDPROC := -4
	local
	
		_hLastFoundWindow := WinExist()
		_GUI := A_DefaultGUI
		GUI, New, +hwnd_GUIID +Resize
		GUI, Show, w300 h300
		GUI, %_GUI%:Default
		WinExist("ahk_id " . _hLastFoundWindow)
		
		_winProcNew := this._winProcNew := CallbackCreate(this._windowProc.bind(this), "", 4)
		; _winProcNew := CallbackCreate(this._windowProc.bind(this), "", 5) ; does the hidden 'this' also to be counted?
		this._winProcOld := DllCall(_winUserFunc, "Ptr", _GUIID, "Int", GWL_WNDPROC, "Ptr", _winProcNew, "Ptr")
		; based on the second exemple from the documentation @registercallback:  https://www.autohotkey.com/docs/commands/RegisterCallback.htm#Examples
		
	}
		_windowProc(_hwnd, _uMsg, _wParam, _lParam) {
			static WM_SIZE := 0x05
			local
			if (_uMsg = WM_SIZE) {
				_w := _lParam & 0xFFFF
				_h := _lParam >> 16
				ToolTip % _w "," _h "|" this.__Class
			}
			return DllCall("CallWindowProc", "Ptr", this._winProcOld, "Ptr", _hwnd, "UInt", _uMsg, "Ptr", _wParam, "Ptr", _lParam)
			
		}
		
	__Delete() {
		MsgBox % A_ThisFunc ; one cannot interact with the MsgBox
		ToolTip % A_ThisFunc
		; sleep, 1000 ; crashes the script
	}
	
}
[EDIT] I finally understood why the MsgBox freezed and why the script crashed: I'm pretty sure that was related to the fact that I was trying to free the callback while its adress was still used for the window procedure... :facepalm:

Code: Select all

G := new GUI()
return
!i::
DllCall((A_PtrSize = 8) ? "SetWindowLongPtr" : "SetWindowLong", "Ptr", G.ID, "Int", -4, "Ptr", G._winProcOld, "Ptr") ; reset the window procedure (I think...)
CallbackFree(G._winProcNew)
return
; ...

Re: [v1] v2's CallbackCreate function for AHK v1.

Posted: 18 Jan 2019, 15:29
by Helgef
Also, I don't know if, passing a func object, I need to take account of the 'this' hidden param for the ParamCount parameter (ParamCount + 1?)
For a method which has a hidden this parameter, that counts as one mandatory parameter. Assuming that the caller passes exactly 4 parameters, you do it right because you bind the first of the five mandatory parameters, so there are 4 parameters left.
[EDIT] I finally understood why the MsgBox freezed and why the script crashed: I'm pretty sure that was related to the fact that I was trying to free the callback while its adress was still used for the window procedure
Yes that explains it.

Cheers.