 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Fri Apr 13, 2007 9:30 pm Post subject: TrackMouseEvent |
|
|
I found great way to create Tooltip module similar to Titan's Anchor, and to do some other interesting things, without the timer. It is in monitoring message WM_MOUSEHOVER and others that should fire after some time mouse is under the client area.
I can not make it to work.
This is the script:
| Code: | #SingleInstance, force
WM_MOUSEHOVER = 0x2A1
TME_HOVER = 0x1
Gui, +LastFound
hwnd := WinExist()
Gui, Add, Text, vTxt1, some kewl text
Gui, Add, Text, vTxt2, some kewl text
Gui, Add, Text, vTxt3, some kewl text
Gui, Show, Autosize
VarSetCapacity(ET, 16, 1)
InsertInteger(16, ET, 0)
InsertInteger(TME_HOVER, ET, 4)
InsertInteger(hwnd, ET, 8)
InsertInteger(500, ET, 12)
;HexView(ET, 16)
r := DllCall("TrackMouseEvent", "uint", &ET)
OnMessage(0x2A1, "OnHover")
return
OnHover(){
msgbox
}
|
HexView shows that the message is properly formated:
However, WIn SPy shows that zero messages are sent to window, while TrackMouseEvent that enables this message returns 1 meaning everything is OK.
If anybody can help figure out this, we can get kewl automatic tooltips without the timer, mouse hover detection etc...
Reference
http://msdn2.microsoft.com/en-us/library/ms645613.aspx
http://msdn2.microsoft.com/en-us/library/ms646265.aspx
http://msdn2.microsoft.com/en-us/library/ms645604.aspx _________________
 |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 338
|
Posted: Sun Apr 15, 2007 9:55 am Post subject: |
|
|
Maybe something like this using MouseMove instead:
| Code: | text1 := "This is text 1"
text2 := "This is text 2"
gui,add,text,,%text1%
gui,add,text,,%text2%
gui,add,button,,Ok
gui,show
OnMessage(0x200,"MouseMove")
return
MouseMove()
{
global
MouseGetPos,,,outW,outC
ControlGetText, outT, %outC%, ahk_id %outW%
SetTimer,killTip,5000
If(outC="")
{ ToolTip
Return
}
If(outT = text1)
{ tooltip,you are over %outC%
}
Else If(outC = "Static2")
{ tooltip,%outC% text is "%text2%"
}
Else If(outT = "Ok")
{ ToolTip, This button is A-Ok!
}
}
killTip:
ToolTip
SetTimer,killTip,off
Return |
_________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3626 Location: Belgrade
|
Posted: Mon Apr 16, 2007 12:03 am Post subject: |
|
|
Well, I wanted to use just this message as it seemd convenient and the implementation would be very simple _________________
 |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 338
|
Posted: Sun Apr 22, 2007 8:34 am Post subject: |
|
|
Well, for simple, try this:
| Code: | 1static1 := "This is text1"
1static2 := "This is text2"
1button1 := "This is the ok button."
gui,add,text,,text1 - very stupid!
gui,add,text,,text2 - important stuff
gui,add,button,,Ok
x1 := (A_ScreenWidth/2)-50
gui,show,x%x1%
2static1 := "This is other gui, still text1"
2static2 := "This is other gui, still text 2"
2button1 := "Still the ok button..."
gui,2:add,text,,text1 - very smart!
gui,2:add,text,,text2 - not so important stuff
gui,2:add,button,,Ok
x2 := (A_ScreenWidth/2)+100
gui,2:show,x%x2%
OnMessage(0x200,"WM_MOUSEMOVE")
Return
guiClose:
ExitApp
Return
WM_MOUSEMOVE()
{
global
MouseGetPos,,,tipGui_outW,tipGui_outC
If(tipGui_outC != tipGui_OLDoutC)
{ tipGui_OLDoutC := tipGui_outC
Gui, %A_Gui%:+LastFound
tipGui_ID := WinExist()
SetTimer,tipGui_killTip,500
tooltip, % %A_Gui%%tipGui_outC%,,,20
}
Return
tipGui_killTip:
MouseGetPos,,,tipGui_outWm
If(tipGui_outWm != tipGui_ID) or (A_TimeIdlePhysical >= 5000)
{ ToolTip,,,,20
SetTimer,tipGui_killTip,Off
}
Return
}
| To make a tooltip for a given control, just set a variable | Code: | | 1button1 := "This is the ok button." | where the first character is the gui number (similar to gui commands -- 2guiClose, etc.) and then the classnn of the control.
The first control of a certain type added to the gui is 1 and so on. The only caveat might be that pictures and texts have a class name of 'static', so that has to be kept in mind. It emulates the real tooltips, timing out after 5 seconds or so if no activity. All vars used in the func are prefixed with 'tipGui_' to prevent collision with existing vars. Also, the tooltip used is 20, for the same reason.
[EDIT]
After posting this, I did a search for 'tooltip' on the forum and found that I had just reinvented the wheel. My solution is almost identical to what was already out there. Mine is an improvement in that it works with multiple guis though. _________________
 |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 338
|
Posted: Fri Jul 20, 2007 8:37 am Post subject: |
|
|
And more improvement. Now provide the text, variable, classnn, or hwnd to assign a tooltip.
Example usage to create a tooltip for an "Ok" button : | Code: | | setTip("Ok",0,"Begin the Process") ;using the caption |
toolTips.ahk | Code: | ;*************gui1*********************
Gui, Add, Button,,Click to do nothing
Gui, Add, DropDownList,vDDL,red|blue|green||
Gui, Add, Checkbox,, Click to enable
Gui, Add, Edit, HwndMYEdit,This is an edit box
Gui, Add, Button,, Ok
Gui, Add, Button, x+ yp, Cancel
Gui, Add, Button, x+ yp, Retry
Gui, Show,x200
;set tooltips for each button - supply text, variable, classnn, or hwnd
setTip(0,"Button1","This button does absolutely nothing.") ;using the classnn
setTip("Ok",0,"Begin the Process") ;using the caption
setTip("Cancel",0,"Cancel Whatever is Happening!")
setTip("Retry",0,"Do Over")
setTip("Click to enable",0,"Checkbox")
setTip(DDL,0,"Dropdownlist") ;using the variable
setTip(MYEdit,0,"The infamous edit control") ;using the hwnd
;*************gui2*********************
Gui, 2:Add, Button,,Click to do nothing
Gui, 2:Add, DropDownList,vDDL2,red|blue|green||
Gui, 2:Add, Checkbox,, Click to enable
Gui, 2:Add, Edit, HwndMYEdit2,This is edit box two
Gui, 2:Add, Button,, Ok
Gui, 2:Add, Button, x+ yp, Cancel
Gui, 2:Add, Button, x+ yp, Retry
Gui, 2:Show,x400
;set tooltips for each button - supply text, variable, classnn, or hwnd
setTip(0,"Button1","This button does absolutely nothing. gui2",2) ;using the classnn
setTip("Ok",0,"Begin the Process gui2",2) ;using the caption
setTip("Cancel",0,"Cancel Whatever is Happening! gui2",2)
setTip("Retry",0,"Do Over gui2",2)
setTip("Click to enable",0,"Checkbox gui2",2)
setTip(DDL2,0,"Dropdownlist part two: This time it's personal",2) ;using the variable
setTip(MYEdit2,0,"The infamous edit control redeux",2) ;using the hwnd
TipsState(1) ;enable tooltips
Return
;*****************tooltip stuff - toolTips.ahk**************************
;if you specify the caption/text use 0 for ClassNN
;if you specify the ClassNN, use 0 for tipControl
setTip(tipControl,tipClassNN,tipText,guiNum=1) ;tipControl - text,variable,hwnd ; tipClassNN - classnn ; tipText - text to display ; gui number, default is 1
{
global
Gui,%guiNum%:+LastFound
WinGet, tipGui_guiID, ID
Gui,%guiNum%:Submit,NoHide
If(tipClassNN) ;if classnn supplied,
{ tipGui_ClassNN := tipClassNN ;use it
}
Else ;if text/var supplied,
{ tipGui_ClassNN := tipGui_getClassNN(0,tipControl,guiNum) ;use it
}
If(!tipGui_ClassNN) ;no classnn returned, must have supplied the hwnd
{ ControlGet, tipGui_tipID, Hwnd,,, ahk_id %tipControl% ;get ID for control
tipGui_ClassNN := tipGui_getClassNN(tipGui_tipID,0,guiNum) ;get classnn using id
}
tipGui_%guiNum%_%tipGui_ClassNN% = %tipText% ;set the tip
}
TipsState(ShowToolTips)
{
If(ShowToolTips)
{ OnMessage(0x200,"WM_MOUSEMOVE") ;enable tips
}
Else
{ OnMessage(0x200,"") ;disable tips
}
}
WM_MOUSEMOVE()
{
global
IfEqual,A_Gui,,Return
MouseGetPos,,,tipGui_outW,tipGui_outC
If(tipGui_outC != tipGui_OLDoutC)
{ tipGui_OLDoutC := tipGui_outC
Gui, %A_Gui%:+LastFound
tipGui_ID := WinExist()
SetTimer,tipGui_killTip,1000
counter := A_TickCount + 500
Loop
{ MouseGetPos,,,,tipGui_newC
IfNotEqual,tipGui_outC,%tipGui_newC%,Return
looper := A_TickCount
IfGreater,looper,%counter%,Break
sleep,50
}
tooltip, % tipGui_%A_Gui%_%tipGui_outC%,,,20
}
Return
tipGui_killTip:
MouseGetPos,,,tipGui_outWm
If(tipGui_outWm != tipGui_ID) or (A_TimeIdle >= 4000)
{ ToolTip,,,,20
SetTimer,tipGui_killTip,Off
}
Return
}
tipGui_getClassNN(kID,kTxt=0,g=1) ;kID = control Hwnd ;kTxt = control text, default=0 ;g = gui number, default=1
{
Gui,%g%:+LastFound
guiID := WinExist() ;get the id for the gui
If(kTxt) and (!kID) ;don't do this if the id is provided
{ mm := A_TitleMatchMode
SetTitleMatchMode,3 ;exact match only
ControlGet,o,hWnd,,%kTxt%,ahk_id %guiID% ;get the id
SetTitleMatchMode,%mm% ;restore previous setting
If(o) ;found match
{ kID := o ;set sought-after id
}
}
WinGet, controls, ControlList, ahk_id %guiID%
Loop, Parse, controls, `n
{ ControlGet,o,hWnd,,%A_LoopField%,ahk_id %guiID% ;get the id
If(o = kID) ;found it
{ Return A_Loopfield ;return the classnn
}
}
}
;*****************end tooltip stuff**************************
|
_________________

Last edited by Micahs on Thu May 01, 2008 12:49 am; edited 3 times in total |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1355
|
Posted: Fri Jul 20, 2007 1:12 pm Post subject: |
|
|
if you create a window and have a tooltip on button1 and then submit/destroy that window, will the tooltip then not also be shown on the main window that created the child window you wanted the tooltip to operate on?
i cant see how supplying the gui number does anything. all you do is submit it. this doesnt actually specify anything. am i missing doing something? any help? |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 338
|
Posted: Sun Jul 22, 2007 6:39 am Post subject: |
|
|
Yep, you are right! I changed so much from the previous version that I accidentally took that stuff out. It now works correctly. Thanks for noticing.
Also, I added a second gui to the example. _________________
 |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1355
|
Posted: Sun Jul 22, 2007 5:27 pm Post subject: |
|
|
| very nice. ive tried it out in my script and it works so much nicer than my previous method, although 1 tiny thing is that this method can make the cpu use go up to 10% if you move quick enough through the tips, where it was idle before. I think a sleep is needed. |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 338
|
Posted: Mon Jul 23, 2007 9:03 pm Post subject: |
|
|
I think you are partially correct. However, if you disable tooltips and move the mouse quickly over the gui the cpu usage also rises.
My system (950mhz Athlon XPsp2) shows a peak of 20% usage with tooltips disabled. Enabled, it peaked at 33%. (I also made another script with a dummy gui and nothing else, which peaked at about 20% usage, too.)
I reworked the MOUSEMOVE function and it now shows a max of about 20% enabled or disabled.
It also more closely mimics the real tooltips, which have a slight delay before appearing. If you move the mouse off the control before the delay expires, the tooltip won't appear, either.
Thanks for the interest! I may move this to it's own thread if there's enough action. _________________
 |
|
| Back to top |
|
 |
TodWulff
Joined: 29 Dec 2007 Posts: 99
|
Posted: Tue Apr 29, 2008 10:36 pm Post subject: |
|
|
I cannot get either of the scripts to work. Has anyone experienced success on a winxp sp2 box running ahk v1.0.47.06?
Please review and advise.
Thank you.
-t
Actually, I got the code in this post above to work. But the last script does not. _________________ When replying, please feel free to address me as Tod or t. My AHK.net site... |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 338
|
Posted: Thu May 01, 2008 12:51 am Post subject: |
|
|
I'm not sure why, but I had this | Code: | | TipsState(0) ;enable tooltips | instead of this | Code: | | TipsState(1) ;enable tooltips |
I corrected it in the last post. Try it now. _________________
 |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 2558 Location: Australia, Qld
|
Posted: Thu May 01, 2008 8:51 am Post subject: |
|
|
I think majkinetor was missing...
| MSDN - TRACKMOUSEEVENT Structure wrote: | TME_HOVER
...
This flag is ignored if the mouse pointer is not over the specified window or area.
| ...and... | MSDN - WM_MOUSEHOVER Notification wrote: | Hover tracking stops when WM_MOUSEHOVER is generated. The application must call TrackMouseEvent again if it requires further tracking of mouse hover behavior.
|
The following demonstrates one way to use TrackMouseEvent and WM_MOUSEHOVER:
| Code: | #SingleInstance, force
Gui, Add, Text, vTxt1, first text
Gui, Add, Text, vTxt2, second text
Gui, Add, Text, vTxt3, third text
Gui, Add, Edit, vEdt1, edit!
Gui, Show
OnMessage(0x200, "OnMouseMove") ; WM_MOUSEMOVE
OnMessage(0x2A1, "OnMouseHover") ; WM_MOUSEHOVER
return
GuiClose:
ExitApp
OnMouseMove(wParam, lParam, msg, hwnd)
{
static TrackWnd, TrackPos
; Ignore repeat WM_MOUSEMOVE messages if position hasn't changed.
if (TrackWnd = hwnd && TrackPos = lParam)
return
ToolTip
VarSetCapacity(ET, 16)
NumPut(16 , ET, 0)
NumPut(0x3 , ET, 4) ; TME_HOVER=1, TME_LEAVE=2
NumPut(hwnd , ET, 8)
NumPut(500 , ET, 12)
TrackWnd := hwnd
TrackPos := lParam
DllCall("TrackMouseEvent", "uint", &ET)
}
OnMouseHover(wParam, lParam, msg, hwnd)
{
WinGetClass, class, ahk_id %hwnd%
ToolTip %class%
}
| It seems WM_MOUSEMOVE is posted to the GUI instead of the Text controls. One workaround is to use MouseGetPos in OnMouseHover to determine which control the mouse is really hovering over. |
|
| Back to top |
|
 |
TodWulff
Joined: 29 Dec 2007 Posts: 99
|
Posted: Sat May 03, 2008 4:03 am Post subject: |
|
|
| Micahs wrote: | | I corrected it in the last post. Try it now. |
It works as advertised. Thank you.
-t _________________ When replying, please feel free to address me as Tod or t. My AHK.net site... |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|