ToolTip Falows mouse

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
aliztori
Posts: 119
Joined: 19 Jul 2022, 12:44

ToolTip Falows mouse

Post by aliztori » 06 Dec 2022, 15:42

hello i wrote a code about tooltipp that falows mouse in ahk2 but its actulai buggy can somone help?

Code: Select all

    Luck(Text?, Time?, Timer := false)
    {

        SetTimer(T, 1)
        Return
        
        T()
        {
            If (!isset(Text) || Time = 0)
            {
                ToolTip()
                SetTimer(T, 0)
                return
            }
            
            ToolTip(Text?)
            IsSet(Time) ? Time-- : ""

        } 
    }

^g::Luck("ali",100)
^b::Luck() ;This is not working and this is my problem

Leafk
Posts: 30
Joined: 11 Nov 2022, 22:09

Re: ToolTip Falows mouse

Post by Leafk » 06 Dec 2022, 17:48

^b looks like is not working because there's no text and time set. And it is effectivelly returning on line 13.
You can assign some default value for both of then using the following line at the beginning of the function Luck()

Code: Select all

Luck(Text?, Time?, Timer := false){
	Time := (isSet(Time))?Time:100 ;Default time of 100 if not declared
	Text := (isSet(Text))?Text:"Default text"
	SetTimer(T, 1)
	Return
	T(){
		If (!isset(Text) || Time = 0){
				ToolTip()
				SetTimer(T, 0)
				return
		}
		ToolTip(Text?)
		IsSet(Time) ? Time-- : ""
	} 
}


Reading your code I was thinking how I would do myself if using recursion (my usual aproach is with a normal loop). Just sharing a different aproach

Code: Select all

Luck(Text:="Default text", Time:=100)
{
	T() ;Start recursive loop
	T()
	{
		If (Time==0)
		{
			ToolTip()
			return
		}
		ToolTip(text)
		Time--
		SetTimer T, -1
	}
}

Tomshi
Posts: 6
Joined: 06 Sep 2022, 20:58
Contact:

Re: ToolTip Falows mouse

Post by Tomshi » 07 Dec 2022, 00:12

I maintain a tooltip class that offers this functionality (and a bit more). Another thing that comes in handy is only redrawing the tooltip if the cursor has actually moved (otherwise you can end up with a flashing tooltip) :)

https://github.com/Tomshiii/ahk/blob/dev/lib/Classes/tool.ahk#L23

aliztori
Posts: 119
Joined: 19 Jul 2022, 12:44

Re: ToolTip Falows mouse

Post by aliztori » 07 Dec 2022, 03:02

Leafk wrote:
06 Dec 2022, 17:48
^b looks like is not working because there's no text and time set. And it is effectivelly returning on line 13.
You can assign some default value for both of then using the following line at the beginning of the function Luck()

Code: Select all

Luck(Text?, Time?, Timer := false){
	Time := (isSet(Time))?Time:100 ;Default time of 100 if not declared
	Text := (isSet(Text))?Text:"Default text"
	SetTimer(T, 1)
	Return
	T(){
		If (!isset(Text) || Time = 0){
				ToolTip()
				SetTimer(T, 0)
				return
		}
		ToolTip(Text?)
		IsSet(Time) ? Time-- : ""
	} 
}


Reading your code I was thinking how I would do myself if using recursion (my usual aproach is with a normal loop). Just sharing a different aproach

Code: Select all

Luck(Text:="Default text", Time:=100)
{
	T() ;Start recursive loop
	T()
	{
		If (Time==0)
		{
			ToolTip()
			return
		}
		ToolTip(text)
		Time--
		SetTimer T, -1
	}
}
hanks dude but Not setting the time is a bit vague. I want to use this tooltip function to follow the movement of the mouse, and when I don't set it and don't give a value Like

Code: Select all

Luck()
, it will turn off the tooltip.

Leafk
Posts: 30
Joined: 11 Nov 2022, 22:09

Re: ToolTip Falows mouse

Post by Leafk » 07 Dec 2022, 06:56

Ahh ok. Now I understand. I tought your bug was because Luck() was not running at all.

Code: Select all

isLuckTimerOn := false
Luck(Text?, Time?){
	global isLuckTimerOn
	isLuckTimerOn := isSet(Text)?true:false
	SetTimer(T, 1)
	Return
	T(){
		If (!isset(Text) || isLuckTimerOn = false){
				ToolTip()
				SetTimer(T, 0)
				return
		}
		ToolTip(Text?)
		IsSet(Time) ? Time-- : ""
	} 
}

^g::Luck("ali",500)
^b::Luck()
My solution uses a global variable to monitor and stop the running loop, this is my usual way to break in my first interation of my code (unclean code).
If a global variable is bad (you don't want to use), another alternative is creating a custom class to enclose everything.

As my motto is there's always more than one way. Here another aproach using a class now (there's room to clean more this code also)

Code: Select all

Class Luck{
	isTimerOn := False
	__New(_Text?, _Time?){
		Luck.isTimerOn := IsSet(_Text)?true:false
		Luck.Text := IsSet(_Text)?_Text:""
		Luck.Count := IsSet(_Time)?_Time:0
		this.runTimer := ObjBindMethod(this, "timerMethod")
		SetTimer this.runTimer, 1
	}
	timerMethod(){
		if (!Luck.isTimerOn || Luck.Count<0){
			ToolTip()
			SetTimer this.runTimer, 0
		}
		ToolTip(Luck.Text)
		Luck.Count--
	}
}

^g::Luck("ali",500)
^b::Luck()

aliztori
Posts: 119
Joined: 19 Jul 2022, 12:44

Re: ToolTip Falows mouse

Post by aliztori » 07 Dec 2022, 11:18

Leafk wrote:
07 Dec 2022, 06:56
Ahh ok. Now I understand. I tought your bug was because Luck() was not running at all.

Code: Select all

isLuckTimerOn := false
Luck(Text?, Time?){
	global isLuckTimerOn
	isLuckTimerOn := isSet(Text)?true:false
	SetTimer(T, 1)
	Return
	T(){
		If (!isset(Text) || isLuckTimerOn = false){
				ToolTip()
				SetTimer(T, 0)
				return
		}
		ToolTip(Text?)
		IsSet(Time) ? Time-- : ""
	} 
}

^g::Luck("ali",500)
^b::Luck()
My solution uses a global variable to monitor and stop the running loop, this is my usual way to break in my first interation of my code (unclean code).
If a global variable is bad (you don't want to use), another alternative is creating a custom class to enclose everything.

As my motto is there's always more than one way. Here another aproach using a class now (there's room to clean more this code also)

Code: Select all

Class Luck{
	isTimerOn := False
	__New(_Text?, _Time?){
		Luck.isTimerOn := IsSet(_Text)?true:false
		Luck.Text := IsSet(_Text)?_Text:""
		Luck.Count := IsSet(_Time)?_Time:0
		this.runTimer := ObjBindMethod(this, "timerMethod")
		SetTimer this.runTimer, 1
	}
	timerMethod(){
		if (!Luck.isTimerOn || Luck.Count<0){
			ToolTip()
			SetTimer this.runTimer, 0
		}
		ToolTip(Luck.Text)
		Luck.Count--
	}
}

^g::Luck("ali",500)
^b::Luck()
OMG Dude U Saved Med its worked Thnks a lot"But I need to read and learn more about ObjBindMethod and classes XD"

Leafk
Posts: 30
Joined: 11 Nov 2022, 22:09

Re: ToolTip Falows mouse

Post by Leafk » 07 Dec 2022, 11:59

If it helps, I learned about ObjBindMethod today also =P

But yeah. Class is a good tool to understand how it works in v2.
You dont need it all time, but when is necessary and you use it your code flow become easier

Just as a example. One code I've done early this year with globals and functions only (with 1000~1200 lines), and was getting finnicky to extend (a lot of places to look for when changing).

After I've rewriten everything adding 1 core class my code reduced to 500 lines and became really steady.
But in this case a lot of the code was about manipulating one especific object and changing it's state (strongest point about using class).

aliztori
Posts: 119
Joined: 19 Jul 2022, 12:44

Re: ToolTip Falows mouse

Post by aliztori » 07 Dec 2022, 15:18

Leafk wrote:
07 Dec 2022, 11:59
If it helps, I learned about ObjBindMethod today also =P

But yeah. Class is a good tool to understand how it works in v2.
You dont need it all time, but when is necessary and you use it your code flow become easier

Just as a example. One code I've done early this year with globals and functions only (with 1000~1200 lines), and was getting finnicky to extend (a lot of places to look for when changing).

After I've rewriten everything adding 1 core class my code reduced to 500 lines and became really steady.
But in this case a lot of the code was about manipulating one especific object and changing it's state (strongest point about using class).
excellent

Yes, I am learning about the classes, but in the second version it is a bit more complicated and limited, maybe? I do not know
But anyway, thanks for the help

aliztori
Posts: 119
Joined: 19 Jul 2022, 12:44

Re: ToolTip Falows mouse

Post by aliztori » 07 Dec 2022, 15:20

i also replace global var to static and works and i dont know what the exactly the point (i have this function in my script with ahk2.0 and i use the all param of func into global array and i use that in settimer )

Code: Select all

Luck(Text?, Time?)
{
    static isOn

	isOn := isSet(Text) ? true : false

	SetTimer(T, 1)
	Return

	T()
    {
		If !(isset(Text) && isOn)
        {
            ToolTip()
            SetTimer(T, 0)
            return
		}

		ToolTip(Text?)
		IsSet(Time) ? Time-- : ""
	} 
}

aliztori
Posts: 119
Joined: 19 Jul 2022, 12:44

Re: ToolTip Falows mouse

Post by aliztori » 07 Dec 2022, 15:34

and i didnt see wy we used ObjBindMethod
i comment that out and i use that method in class but a have ErrorLevelored but why ?
i dont understand

Code: Select all

; this.runTimer := ObjBindMethod(this, "timerMethod")
SetTimer this.timerMethod(), 1
;or
SetTimer Luck.timerMethod(), 1

Leafk
Posts: 30
Joined: 11 Nov 2022, 22:09

Re: ToolTip Falows mouse

Post by Leafk » 07 Dec 2022, 21:50

Doing ObjBindMethod we are assigning the method/function timeMethod to the property/variable runTimer
Doing with global also works (but the we are going global again)

Code: Select all

global runTimer := ObjBindMethod(this, "timerMethod")
SetTimer runTimer, 1
...
SetTimer runTimer, 0
About globals, I usualy do my first trip with new code using globals, and afterwards I try to remove mostly of the globals.
When your code becomes bigger and bigger there's more chance of reusing the same name of an existing global in another part (and then a new bug someday in some situation can happen)
Before ahk I've made my own big spagetti on my own excel vba and this was one of the reasons for some erratic behavior (error was happening just because at random times)

About not using ObjBindMethod I don't know the "real" reason, I've got the working code from the forum after trying the same as you. And here is my own guess (probably is just remotely close to the truth).

The reason SetTimer is not working with this.timerMethod() directly is because SetTimer expects one object (the function) and is receiving both a class and method, and it fails because of the sintax class.method looks like is not the same as one object (dont know why).

Someday I'll have a better answer, but for now this is all I got =P

Btw, I've run your last code and looks like declaring isOn inside of the function carries over to T() without being a global.
Better than my solution and new knowledge aquired (thanks)

Post Reply

Return to “Ask for Help (v2)”