Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

ToolTip which follows the mouse is flickering


  • Please log in to reply
17 replies to this topic
Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
AHK Basic and AHK_L compatible solution please.
Loop
ToolTip, I flicker - bad. I follow mouse - good.
I only have Win XP, but I've heared that this code flickers on Vista and Win7 because ToolTip window is created over and over again. (It does not flicker on Win XP)

My intention in code above is: just move the tooltip as user moves mouse (do not recreate window).
I was thinking to make a function from this, that would just move tooltip window + update it's text if needed , but my knowledge about ToolTip Class and Tooltip Control Messages is almost 0, so I think I'm not competent enough to do it right. Therefore, I'm asking for help. I would like to have something like this:

Loop
ToolTip("I don't flicker - good. I follow mouse - good.")

ToolTip(text) {
- firstly, create tooltip window and store its hwnd. (CreateWindowEx ?)
- if user moves mouse, move tooltip (do not recreate tooltip window) (TTM_TRACKPOSITION ?)
- if user modifies ToolTip text, update tooltip text (do not recreate tooltip window) (TTM_UPDATETIPTEXT ?)
- if there is no text specified, hide or destroy tooltip window (TTM_DELTOOL ?)
}

Can somebody help? Thanks in advance.

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
I think MoveWindow is the simplest solution (using DllCall as it is much faster).
ToolTip, Hello World
Process,Exist
hwnd:=WinExist("ahk_class tooltips_class32 ahk_pid " ErrorLevel)
WinGetPos,,,w,h,ahk_id %hwnd%
While DllCall("MoveWindow","Uptr",hwnd,"Int",x+10,"Int",y+10,"Int",w,"Int",h,"Int",0)
	MouseGetPos,x,y
Using TT() function you can use Trackposition message.
T:=TT()
T.Show("Hello World")
MouseGetPos,x,y
While !T.TrackPosition(x+10,y+10)
	MouseGetPos,x,y
Here is a solution for any ToolTip by sending the TRACKPOSITION message.
ToolTip, Hello World
Process,Exist
hwnd:=WinExist("ahk_class tooltips_class32 ahk_pid " Errorlevel)
Loop
	ToolTip_UpdatePos(hwnd)

ToolTip_UpdatePos(hwnd,x="",y=""){
	static TTM_TRACKPOSITION := 0x412
	VarSetCapacity(xc, 20, 0), xc := Chr(20),DllCall("GetCursorInfo", "Uint", &xc)
	,yc := NumGet(xc,16), xc := NumGet(xc,12),xc+=10,yc+=10
	If x
		xc:=x
	If y
		yc:=y
	DllCall("SendMessage", A_PtrSize ? "UPTR" : "UInt", hwnd
                                    , "Uint", TTM_TRACKPOSITION
                                    , A_PtrSize ? "UPTR" : "UInt", 0
                                    , A_PtrSize ? "UPTR" : "UInt", (xc & 0xFFFF)|(yc & 0xFFFF)<<16)
}


Guest_
  • Guests
  • Last active:
  • Joined: --
Why do you use UPtr (which is AHK_L exclusive and thus doesn't work under AHK "Basic"), instead of UInt which does the same job anyway, and works on both versions (not everyone that stumbles upon this snippet necessarily has to know the differences between both)...?

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Thanks Guest_, I have updated above to work for any version :)

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
Thank you! Next question: How to update Tooltip text? Here is what I got for now:
;====== Testing area ======
ToolTip, Hello World
Process,Exist
hwnd:=WinExist("ahk_class tooltips_class32 ahk_pid " Errorlevel)
Loop, 100	; moving tooltip - works
{
	ToolTip_UpdatePos(hwnd)
	Sleep, 20
}
ToolTip_UpdateText(hwnd, "NewText")	; changing text - does not work yet.
Loop, 100
{
	ToolTip_UpdatePos(hwnd)
	Sleep, 20
}

;====== Functions ======
ToolTip_UpdateText(hwnd, NewText) {		; does not work yet
   static TTM_UPDATETIPTEXT = A_IsUnicode?0x439:0x40c
    
	DllCall("SendMessage", A_PtrSize ? "UPTR" : "UInt", hwnd
                                    , "Uint", TTM_UPDATETIPTEXT
                                    , A_PtrSize ? "UPTR" : "UInt", 0
                                    , A_PtrSize ? "UPTR" : "UInt", [color=red]???WHAT TO PUT HERE???[/color])	; Pointer to a TOOLINFO structure - how to use it there?  NewText --> lpszText ???
}

ToolTip_UpdatePos(hwnd,x="",y=""){		; works
	static TTM_TRACKPOSITION := 0x412
	VarSetCapacity(xc, 20, 0), xc := Chr(20),DllCall("GetCursorInfo", "Uint", &xc)
	,yc := NumGet(xc,16), xc := NumGet(xc,12),xc+=10,yc+=10
   If x
      xc:=x
   If y
      yc:=y
   DllCall("SendMessage", A_PtrSize ? "UPTR" : "UInt", hwnd
                                    , "Uint", TTM_TRACKPOSITION
                                    , A_PtrSize ? "UPTR" : "UInt", 0
                                    , A_PtrSize ? "UPTR" : "UInt", (xc & 0xFFFF)|(yc & 0xFFFF)<<16)
}


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

???WHAT TO PUT HERE???

pointer to a TOOLINFOstructure.

If you want it to do for AHK basic and AHK_L + working for 64-bit as well it will be really messy because structure size differs.

You can use ToolTip() function, but it does not support 64-bit.
SetBatchLines,-1
ToolTip(1," ",,"N1") ;N1=do not activate tooltip (NoActivate)
Loop 1000
{
   ToolTip(1,"Count " A_Index,"","GTTM_TRACKACTIVATE")
   Sleep, 20
}
ExitApp


Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
Thanks!
Well, making AHK basic and AHK_L + working for 64-bit function to update tooltip text is too advanced for me, therefore, I'm forced to stop here.

If somebody has knowledge and patience to do it, it would be great...

Mtes
  • Members
  • 27 posts
  • Last active: Aug 15 2013 03:09 PM
  • Joined: 17 Feb 2011
Hello.

I was searching for flickering issue and found this post. HotKeyIt's 1st solution works for me, except my intentions are a bit different. I want to display tooltip as long as key is pressed. Here is my code:

~Shift::
~Shift Up::
	CoordMode, ToolTip, Screen
	CoordMode, Mouse, Screen
	ToolTip, SHIFT up
	Process,Exist 
	hwnd:=WinExist("ahk_class tooltips_class32 ahk_pid " ErrorLevel) 
	WinGetPos,,,w,h,ahk_id %hwnd% 
	While DllCall("MoveWindow","Uptr",hwnd,"Int",x+20,"Int",y-10,"Int",w,"Int",h,"Int",0) 
		MouseGetPos,x,y
	return

As you see, i want to remap Shift key to itself, and to retain its full functionality, but to add one feature: as long as it's pressed tooltip should be shown.
Before eliminating flickering issue i used KeyWait or SetTimer Check commands, but now they don't work.
Is there a way to do as i want? Please help.

Thanks.

NoobSawce
  • Members
  • 103 posts
  • Last active: Mar 19 2011 05:11 AM
  • Joined: 15 Feb 2011
First off, I'd like to point out that you've basically hijacked the thread, which is frowned up by most forum communities in general (not just our forums). I would politely suggest posting a new topic in the future, which fully describes your issue, and perhaps provide a link to this topic if you feel it has relevant information for your question. Not only is it better "netiquette," you are also more likely to get a timely response to your question, as posting here means most users would have passed over your post thinking it was an additional comment or solution to some else's problem.

Now then, with that out of the way, as I'm sure you are probably aware (if you've tried this script), the shift key doesn't work, and your tooltip window never disappears until you unload the script. That is basically because your while loop always evaluates to True as long as the call to MoveWindow succeeds (which is practically guaranteed). To correct this, try the following instead (verified):

LShift::
	CoordMode, ToolTip, Screen
	CoordMode, Mouse, Screen
	ToolTip, Shift Up
	Process,Exist
	hwnd:=WinExist("ahk_class tooltips_class32 ahk_pid " ErrorLevel)
	WinGetPos,,,w,h,ahk_id %hwnd%

	Send, {LShift Down}
	While DllCall("MoveWindow","Uptr",hwnd,"Int",x+20,"Int",y-10,"Int",w,"Int",h,"Int",0)
	{
		If (!GetKeyState("LShift", "P")) {
			WinClose, % "ahk_id " . hwnd
			break
		}
		MouseGetPos,x,y
	}
	Send, {LShift Up}
Return


Mtes
  • Members
  • 27 posts
  • Last active: Aug 15 2013 03:09 PM
  • Joined: 17 Feb 2011
Thanks NoobSawce.

And i'm sorry if it was wrong to post in existing thread, but i on the contrary thought it's wiser to post in existing thread, since most of solution to my problem i got here, just wanted to make small modification. But in the future i'll do as appropriate then.

NoobSawce
  • Members
  • 103 posts
  • Last active: Mar 19 2011 05:11 AM
  • Joined: 15 Feb 2011
It's no big offense, just a minor one (like not rinsing your dishes before putting them in the dishwasher), don't worry about it. I was just letting you know because it hurts you more than the rest of us, since it might take longer for you to a get a response than you otherwise might get. Plus, sometimes people searching for solutions to your same problem might get a little confused and assume the post doesn't apply to them.

Glad things are working for you, though. :)

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
WARNING: This is old thread. It is continued here.

Here is a ToolTipFM() function - ToolTip which Follows the Mouse
Now it does not flicker when you move the mouse, but flickers once per text change.
Function:
ToolTipFM(Text="", WhichToolTip=16, xOffset=16, yOffset=16) { ; ToolTip which Follows the Mouse
static LastText, hwnd, VirtualScreenWidth, VirtualScreenHeight ; http://www.autohotkey.com/forum/post-430240.html#430240

if (VirtualScreenWidth = "" or VirtualScreenHeight = "")
{
SysGet, VirtualScreenWidth, 78
SysGet, VirtualScreenHeight, 79
}

if (Text = "") ; destroy tooltip
{
ToolTip,,,, % WhichToolTip
LastText := "", hwnd := ""
return
}
else ; move or recreate tooltip
{
CoordMode, Mouse, Screen
MouseGetPos, x,y
x += xOffset, y += yOffset
WinGetPos,,,w,h, ahk_id %hwnd%

; if necessary, adjust Tooltip position
if ((x+w) > VirtualScreenWidth)
AdjustX := 1
if ((y+h) > VirtualScreenHeight)
AdjustY := 1

if (AdjustX and AdjustY)
x := x - xOffset*2 - w, y := y - yOffset*2 - h
else if AdjustX
x := VirtualScreenWidth - w
else if AdjustY
y := VirtualScreenHeight - h

if (Text = LastText) ; move tooltip
DllCall("MoveWindow", A_PtrSize ? "UPTR" : "UInt",hwnd,"Int",x,"Int",y,"Int",w,"Int",h,"Int",0)
else ; recreate tooltip
{
; Perfect solution would be to update tooltip text (TTM_UPDATETIPTEXT), but must be compatible with all versions of AHK_L and AHK Basic.
; My Ask For Help link: http://www.autohotkey.com/forum/post-421841.html#421841
CoordMode, ToolTip, Screen
ToolTip,,,, % WhichToolTip ; destroy old
ToolTip, % Text, x, y, % WhichToolTip ; show new
hwnd := WinExist("ahk_class tooltips_class32 ahk_pid " DllCall("GetCurrentProcessId")), LastText := Text
%A_ThisFunc%(Text, WhichToolTip, xOffset, yOffset) ; move new
}
Winset, AlwaysOnTop, on, ahk_id %hwnd%
}
}
Edit 07.05.2011.: fixed positioning on multi-monitors. Thanks to musketball and me lance for testing.
Testing area:
; Press and hold F1-F4 hotkeys, and move mouse.

Text = ; Make too long ToolTip text for testing purpose
(
If blank or omitted, the existing tooltip (if any) will be hidden.
Otherwise, this parameter is the text to display in the tooltip.
If blank or omitted, the existing tooltip (if any) will be hidden.
Otherwise, this parameter is the text to display in the tooltip.
If blank or omitted, the existing tooltip (if any) will be hidden.
Otherwise, this parameter is the text to display in the tooltip.
If blank or omitted, the existing tooltip (if any) will be hidden.
Otherwise, this parameter is the text to display in the tooltip.
If blank or omitted, the existing tooltip (if any) will be hidden.
Otherwise, this parameter is the text to display in the tooltip.
If blank or omitted, the existing tooltip (if any) will be hidden.
Otherwise, this parameter is the text to display in the tooltip.
If blank or omitted, the existing tooltip (if any) will be hidden.
Otherwise, this parameter is the text to display in the tooltip.
)


;=== Test ToolTip mouse following ===
F1:: ; old system = flickers + high CPU load + slow moving
While, GetKeyState(A_ThisHotkey,"p")
{
Sleep, 20
ToolTip, % text
}
ToolTip
return

F2:: ; new system = does not flicker + low CPU load + fast moving
While, GetKeyState(A_ThisHotkey,"p")
{
Sleep, 20
ToolTipFM(Text)
}
ToolTipFM()
return


;=== Test ToolTip mouse following + text change ===
F3:: ; old system = flickers + high CPU load + slow moving
; Note: It's so slow that you'll need to hold hotkey for a long time to wait text to change.
c := 0
While, GetKeyState(A_ThisHotkey,"p")
{
Sleep, 20
c++
if (c < 100)
ToolTip, % Text
else if (c < 200)
ToolTip, % (SubStr(Text,1,50))
else
c = 0
}
ToolTip
return

F4:: ; new system = one flicker per text change + low CPU load + fast moving
c := 0
While, GetKeyState(A_ThisHotkey,"p")
{
Sleep, 20
c++
if (c < 100)
ToolTipFM(Text)
else if (c < 200)
ToolTipFM(SubStr(Text,1,50))
else
c = 0
}
ToolTipFM()
return
Everyone is welcome to improve it - to use TTM_UPDATETIPTEXT instead of Tooltip recreation, but must be compatible with all versions of AHK_L and AHK Basic

aaronbewza
  • Members
  • 466 posts
  • Last active: Feb 05 2013 08:40 AM
  • Joined: 20 Feb 2011
Thank you very much for this tooltip function... I've been looking for a non-flickery tooltip for weeks! The other ones I've tried are flickery or I could not figure out how to make it work.
thanks again :)

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
You are welcome.

123
  • Guests
  • Last active:
  • Joined: --
I'm trying to do this flicking effect of the tooltip, but with a Window, I'd like a Window which title starts by "Dictator - " to follow with some distance from the mouse, but I don't know enough about AHK to make the changes :p

I added a delay at the end of the loop, bcs it takes much resources, and I don't care if the Window has some delay.

ToolTip, Hello World
Process,Exist
hwnd:=WinExist("ahk_class tooltips_class32 ahk_pid " Errorlevel)
Loop
   ToolTip_UpdatePos(hwnd)

ToolTip_UpdatePos(hwnd,x="",y=""){
   static TTM_TRACKPOSITION := 0x412
   VarSetCapacity(xc, 20, 0), xc := Chr(20),DllCall("GetCursorInfo", "Uint", &xc)
   ,yc := NumGet(xc,16), xc := NumGet(xc,12),xc+=30,yc+=30
   If x
      xc:=x
   If y
      yc:=y
   DllCall("SendMessage", A_PtrSize ? "UPTR" : "UInt", hwnd
                                    , "Uint", TTM_TRACKPOSITION
                                    , A_PtrSize ? "UPTR" : "UInt", 0
                                    , A_PtrSize ? "UPTR" : "UInt", (xc & 0xFFFF)|(yc & 0xFFFF)<<16)
Sleep, 1000
}