AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

TrackMouseEvent

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Fri Apr 13, 2007 9:30 pm    Post subject: TrackMouseEvent Reply with quote

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
View user's profile Send private message MSN Messenger
Micahs



Joined: 01 Dec 2006
Posts: 338

PostPosted: Sun Apr 15, 2007 9:55 am    Post subject: Reply with quote

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
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Mon Apr 16, 2007 12:03 am    Post subject: Reply with quote

Well, I wanted to use just this message as it seemd convenient and the implementation would be very simple
_________________
Back to top
View user's profile Send private message MSN Messenger
Micahs



Joined: 01 Dec 2006
Posts: 338

PostPosted: Sun Apr 22, 2007 8:34 am    Post subject: Reply with quote

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
View user's profile Send private message
Micahs



Joined: 01 Dec 2006
Posts: 338

PostPosted: Fri Jul 20, 2007 8:37 am    Post subject: Reply with quote

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
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1355

PostPosted: Fri Jul 20, 2007 1:12 pm    Post subject: Reply with quote

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
View user's profile Send private message
Micahs



Joined: 01 Dec 2006
Posts: 338

PostPosted: Sun Jul 22, 2007 6:39 am    Post subject: Reply with quote

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
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1355

PostPosted: Sun Jul 22, 2007 5:27 pm    Post subject: Reply with quote

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
View user's profile Send private message
Micahs



Joined: 01 Dec 2006
Posts: 338

PostPosted: Mon Jul 23, 2007 9:03 pm    Post subject: Reply with quote

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
View user's profile Send private message
TodWulff



Joined: 29 Dec 2007
Posts: 99

PostPosted: Tue Apr 29, 2008 10:36 pm    Post subject: Reply with quote

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
View user's profile Send private message
Micahs



Joined: 01 Dec 2006
Posts: 338

PostPosted: Thu May 01, 2008 12:51 am    Post subject: Reply with quote

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
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 2558
Location: Australia, Qld

PostPosted: Thu May 01, 2008 8:51 am    Post subject: Reply with quote

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
View user's profile Send private message
TodWulff



Joined: 29 Dec 2007
Posts: 99

PostPosted: Sat May 03, 2008 4:03 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group