Page 1 of 1

A simple Class for calling V1's libs in V2

Posted: 16 Oct 2021, 04:48
by viv
Write the following via online translation
I don't know much about Class, so I hope it's not too much of a problem

Test in AutoHotkey v2 2.0-beta.1
Copy the DLL to your script directory or set dllPath
Test in this dll ahkdll-v1-release-master\x64w\AutoHotkey.dll
Thanks to HotKeyIt for their help! viewtopic.php?f=67&t=95612#p425193
Supports up to 10 params

Code: Select all

; Test in AutoHotkey v2 2.0-beta.1
; Copy the DLL to your script directory or set dllPath
; Test in this dll                                             ahkdll-v1-release-master\x64w\AutoHotkey.dll
; Need V1 AutoHotkey.dll                                       https://hotkeyit.github.io/v1/
; Download dll                                                 https://github.com/HotKeyIt/ahkdll-v1-release/archive/master.zip
; Sample need copy func and save in  D:\OSDTIP.ahk             https://www.autohotkey.com/boards/viewtopic.php?f=6&t=76881
; Thanks to HotKeyIt for their help!                           https://www.autohotkey.com/boards/viewtopic.php?f=67&t=95612#p425193
; Supports up to 10 params

; Persistent
; test := IncludeLib("D:\OSDTIP.ahk")  ;(v1 libs path, AutoHotkey.dll path)
; test.do("OSDTIP_Pop","Notification","Message", "-2000")
; Sleep(2000)
; test.do("OSDTIP_Pop","Notification","Message",  "0", "C11 zh7 w160 CW101010 CTD3D3D3 U1 U2",,,"0x00FFFF", "0x808080", "30")
; Sleep(2000)
; test.do("OSDTIP_KBLeds","CapsLock", "", "-2000")
; Sleep(2000)
; test.do("OSDTIP_Volume","+1", "", "-2000")
; Sleep(2000)
; test.do("OSDTIP_Desktop",A_UserName,A_Hour ":" A_Min ":" A_Sec ,"-2000") ;Variables dont need ""
; Sleep(2000)
; test.do("OSDTIP_Alert","MainText","SubText")
; Sleep(2000)
; test := ""
; ExitApp

Class IncludeLib
{

    __New(libPath, dllPath := "")
    {
        if !FileExist(dllPath := dllPath ? dllPath : A_ScriptDir "\AutoHotkey.dll")
            MsgBox("Miss AutoHotkey.dll file"), ExitApp()
        This.hDll := DllCall("LoadLibrary", "Str", dllPath, "Ptr")
        DllCall("AutoHotkey.dll\ahktextdll", "Str", "#Persistent `n#NoTrayIcon `n#include " libPath, "Str", "", "Str", "")
        This.hahkFunction := DllCall("GetProcAddress", "Ptr", This.hDll, "AStr", "ahkFunction", "PTR")
    }

    __Delete()
    {
        DllCall("AutoHotkey.dll\ahkExec", "Str", "ExitApp", "CDecl")
        DllCall("FreeLibrary", "Ptr", This.hDll)
    }

    do(FuncNmae, v*)
    {
        p := []
        Loop 10
            p.Push(v.Has(A_Index) ? v[A_Index] : "")
        ahkFunction := DllCall.Bind(this.hahkFunction, "Str", , "Str", p[1], "Str", p[2], "Str", p[3], "Str", p[4], "Str", p[5], "Str", p[6], "Str", p[7], "Str", p[8], "Str", p[9], "Str", p[10], "CDecl Str")
        return ahkFunction(FuncNmae)
    }
}

Re: A simple Class for calling V1's libs in V2

Posted: 16 Oct 2021, 05:55
by viv
Having a bit of trouble working with ACC and not sure what to do about it

use this in chrome will stuck
viewtopic.php?p=347959#p347959

Stuck on this line

Code: Select all

if DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0
https://github.com/sancarn/ACC.AHK/blob/795d10646f9b90a05d2cc3d7f505b7950ff9db21/AccV2.ahk#L583
or this
https://github.com/sancarn/ACC.AHK/blob/795d10646f9b90a05d2cc3d7f505b7950ff9db21/AccV2.ahk#L614

Re: A simple Class for calling V1's libs in V2

Posted: 18 Oct 2021, 12:09
by Delta Pythagorean
Wouldn't it be better to use the __Call method instead of using the do method?

Re: A simple Class for calling V1's libs in V2

Posted: 19 Oct 2021, 00:48
by viv
@Delta Pythagorean
I am not a programmer and find calss very difficult to use
and the documentation does not have any examples
so I don't really understand what it is used for.

Re: A simple Class for calling V1's libs in V2

Posted: 20 Oct 2021, 06:28
by Delta Pythagorean
The best way to do it is through the __Call meta-method. I've provided some documentation to go along with my version of this class:

Code: Select all

/**
 * Include an AutoHotkey v1 library into an AutoHotkey v2 script/program.
 *
 * @example
 * Persistent(true)
 * test := IncludeLib("<OSDTIP>")
 * test.OSDTIP_Pop("Notification", "Message", "-2000")
 * Sleep(2000)
 * test.OSDTIP_Pop("Notification", "Message", "0", "C11 zh7 w160 CW101010 CTD3D3D3 U1 U2",,, "0x00FFFF", "0x808080", "30")
 * Sleep(2000)
 * test.OSDTIP_KBLeds("CapsLock", "", "-2000")
 * Sleep(2000)
 * test.OSDTIP_Volume("+1", "", "-2000")
 * Sleep(2000)
 * test.OSDTIP_Desktop(A_UserName, Format("{1}:{2}:{3}", A_Hour, A_Min, A_Sec), "-2000") ; Variables dont need ""
 * Sleep(2000)
 * test.OSDTIP_Alert("MainText","SubText")
 * Sleep(2000)
 * test := ""
 * ExitApp(0)
*/
class IncludeLib
{
	/** @type {number} */
	handle_dll := 0

	/** @type {number} */
	handle_ahk_func := 0

	/** @type {string}  */
	lib_path := ""
	
	/** @type {string}  */
	dll_path := ""


	__New(lib_path, dll_path := "")
	{
		this.lib_path := lib_path
		this.dll_path := dll_path ? (dll_path) : (A_ScriptDir . "\AutoHotkey.dll")

		if (!FileExist(this.dll_path))
		{
			throw Error("Invalid or missing dynamic link library file", -1, dll_path)
		}

		try
		{
			this.handle_dll := DllCall("LoadLibrary", "Str", this.dll_path, "Ptr")
		}
		catch Any
		{
			throw Error("Could not load dynamic link library", -1, this.dll_path)
		}
		DllCall(dll_path . "\ahktextdll", "Str", "#Persistent `n#NoTrayIcon `n#include " . this.lib_path, "Str", "", "Str", "")
		this.handle_ahk_func := DllCall("GetProcAddress", "Ptr", this.handle_dll, "AStr", "ahkFunction", "PTR")
	}

	__Delete()
	{
		DllCall(this.dll_path . "\ahkExec", "Str", "ExitApp", "CDecl")
		DllCall("FreeLibrary", "Ptr", this.handle_dll)
	}

	__Call(func_name, args*)
	{
		params := []
		params.Push("Str", "")
		for index, value in args
		{
			if (value == "") || (!value)
			{
				params.Push("Str", "")
				continue
			}

			if (this._TypeOf(value) !== "String")
			{
				type_of := this._TypeOf(value)
				throw Error("Expected a string, got a" . (type_of == "Array" ? "n") . " " . type_of, -1, "args[" . index . "]")
			}

			params.Push("Str", value)
		}
		params.Push("CDel Str")

		ahk_func := DllCall.Bind(this.handle_ahk_func, params*)		; Should look like: DllCall(this.handle_ahk_func, "Str", "", ("Str", params) ... , "CDel Str")

		try
		{
			return ahk_func(func_name)
		}
		catch Any as err
		{
			throw err
		}
	}

	_TypeOf(Value)
	{
		if ((comClass := ComObjType(Value, "Class")) != "")
		{
			return comClass
		}

		try ; `Value is Object` is not checked because it can be false for prototypes.
		{
			if (ObjHasOwnProp(Value, "__Class"))
			{
				return "Prototype"
			}
		}

		while (Value := ObjGetBase(Value))
		{
			if (ObjHasOwnProp(Value, "__Class"))
			{
				return Value.__Class
			}
		}

		return "Object"
	}
}
EDIT: Fixed a few things such as where the AHK.DLL file resides not being used and allowing more than 10 parameters for the DllCall to the function residing in the library.
As for the codeblock highlighting the rest of the code into a comment because multi-line comments aren't implemented with v2's style, I refuse to change my ways :P

Re: A simple Class for calling V1's libs in V2

Posted: 20 Oct 2021, 06:36
by jNizM
OT @Delta Pythagorean
The multi-line comments (/* */) as one-line comment breaks the forum codbox highlighter. Use ; for one-line comments

Or @joedf can you push a fix for this?

Re: A simple Class for calling V1's libs in V2

Posted: 20 Oct 2021, 07:52
by kczx3
Multi line comments are used because some editors highlight words that start with @ differently within those comments. Typically called Comment Docs, I think.

Re: A simple Class for calling V1's libs in V2

Posted: 20 Oct 2021, 07:57
by viv
@Delta Pythagorean

Thank you very much
As a non-programmer, I don’t pay much attention to throwing mistakes

But the example fails to run...
TIPs : Error: Expected a String but got an Array.
I guess there is a problem with the incoming parameters
I tested it with reference to
args is not passed in

Code: Select all

i := test()
i.do("1","2","3")
class test
{
	__Call(test1,args*)
	{
		MsgBox test1 ;has test1
		MsgBox args.length ;have length 1
		for i in args ;but nothing in array?
			MsgBox i
	}
}

Re: A simple Class for calling V1's libs in V2

Posted: 20 Oct 2021, 10:18
by Tre4shunter
[EDIT] disregard, apparently i was using not latest beta version.

Im unable to get either example with OSDTIP to work?

failing here for some reason?

Code: Select all

        DllCall("AutoHotkey.dll\ahktextdll", "Str", "#Persistent `n#NoTrayIcon `n#include " libPath, "Str", "", "Str", "")
i have the autohotkey.dll in my main script dir. It's a 'Failed to load dll' Error.

ideas?

Re: A simple Class for calling V1's libs in V2

Posted: 20 Oct 2021, 11:20
by HotKeyIt
It should be DllCall(dll_path "\ahktextdll", "Str", "#Persistent `n#NoTrayIcon `n#include " . lib_path, "Str", "", "Str", "")

Re: A simple Class for calling V1's libs in V2

Posted: 21 Oct 2021, 18:17
by Tre4shunter
Im really struggling to understand why @Delta Pythagorean's version of the OPs script does not work.

it states "Expected a String but got an Array." I've tried my best to understand this one, but cant seem to make it work....if anyone could perhaps shed some light id be very grateful.

Thanks!

-Tr4

Re: A simple Class for calling V1's libs in V2

Posted: 22 Oct 2021, 09:17
by Tre4shunter
Delta Pythagorean wrote:
20 Oct 2021, 06:28
The best way to do it is through the __Call meta-method. I've provided some documentation to go along with my version of this class:

Code: Select all

/**
 * Include an AutoHotkey v1 library into an AutoHotkey v2 script/program.
 *
 * @example
 * Persistent(true)
 * test := IncludeLib("<OSDTIP>")
 * test.OSDTIP_Pop("Notification", "Message", "-2000")
 * Sleep(2000)
 * test.OSDTIP_Pop("Notification", "Message", "0", "C11 zh7 w160 CW101010 CTD3D3D3 U1 U2",,, "0x00FFFF", "0x808080", "30")
 * Sleep(2000)
 * test.OSDTIP_KBLeds("CapsLock", "", "-2000")
 * Sleep(2000)
 * test.OSDTIP_Volume("+1", "", "-2000")
 * Sleep(2000)
 * test.OSDTIP_Desktop(A_UserName, Format("{1}:{2}:{3}", A_Hour, A_Min, A_Sec), "-2000") ; Variables dont need ""
 * Sleep(2000)
 * test.OSDTIP_Alert("MainText","SubText")
 * Sleep(2000)
 * test := ""
 * ExitApp(0)
*/
class IncludeLib
{
	/** @type {number} */
	handle_dll := 0

	/** @type {number} */
	handle_ahk_func := 0

	/** @type {string}  */
	lib_path := ""
	
	/** @type {string}  */
	dll_path := ""


	__New(lib_path, dll_path := "")
	{
		this.lib_path := lib_path
		this.dll_path := dll_path ? (dll_path) : (A_ScriptDir . "\AutoHotkey.dll")

		if (!FileExist(this.dll_path))
		{
			throw Error("Invalid or missing dynamic link library file", -1, dll_path)
		}

		try
		{
			this.handle_dll := DllCall("LoadLibrary", "Str", this.dll_path, "Ptr")
		}
		catch Any
		{
			throw Error("Could not load dynamic link library", -1, this.dll_path)
		}
		DllCall(dll_path . "\ahktextdll", "Str", "#Persistent `n#NoTrayIcon `n#include " . this.lib_path, "Str", "", "Str", "")
		this.handle_ahk_func := DllCall("GetProcAddress", "Ptr", this.handle_dll, "AStr", "ahkFunction", "PTR")
	}

	__Delete()
	{
		DllCall(this.dll_path . "\ahkExec", "Str", "ExitApp", "CDecl")
		DllCall("FreeLibrary", "Ptr", this.handle_dll)
	}

	__Call(func_name, args*)
	{
		params := []
		params.Push("Str", "")
		for index, value in args
		{
			if (value == "") || (!value)
			{
				params.Push("Str", "")
				continue
			}

			if (this._TypeOf(value) !== "String")
			{
				type_of := this._TypeOf(value)
				throw Error("Expected a string, got a" . (type_of == "Array" ? "n") . " " . type_of, -1, "args[" . index . "]")
			}

			params.Push("Str", value)
		}
		params.Push("CDel Str")

		ahk_func := DllCall.Bind(this.handle_ahk_func, params*)		; Should look like: DllCall(this.handle_ahk_func, "Str", "", ("Str", params) ... , "CDel Str")

		try
		{
			return ahk_func(func_name)
		}
		catch Any as err
		{
			throw err
		}
	}

	_TypeOf(Value)
	{
		if ((comClass := ComObjType(Value, "Class")) != "")
		{
			return comClass
		}

		try ; `Value is Object` is not checked because it can be false for prototypes.
		{
			if (ObjHasOwnProp(Value, "__Class"))
			{
				return "Prototype"
			}
		}

		while (Value := ObjGetBase(Value))
		{
			if (ObjHasOwnProp(Value, "__Class"))
			{
				return Value.__Class
			}
		}

		return "Object"
	}
}
EDIT: Fixed a few things such as where the AHK.DLL file resides not being used and allowing more than 10 parameters for the DllCall to the function residing in the library.
As for the codeblock highlighting the rest of the code into a comment because multi-line comments aren't implemented with v2's style, I refuse to change my ways :P
Appreciate the updates, im learning lots....but i still cant get your version of this class to work, no matter what i try? Also - are you missing something here?

Code: Select all

params.Push("CDel Str")..shoudnt it be "Cdecl Str"
Sorry to be such a bother with this..

Thanks again