Welcome to Joel Lipman .Com

Preparing Content...


Loading...

Our Website Development Notes

We hope this helps!

Articles // Automation // AutoHotkey

Add Image Mouseover effect in AutoHotkey GUI

Thursday, 7th July 2011
202,705 Reads

 Couldn't find this anywhere on the net and kinda needed it so am making a note of how to do it here.

The issue is that I wanted to make my autohotkey program change the image that the mouse hovers over (within it's own GUI).  No third-party component or dll needed, just a slight modification to the mousemove tooltip in the autohotkey manual.

 The following code is not the whole code or a working program but should demonstrate how to include it in your own Autohotkey GUI:

  1. ; SET TOOLTIP TEXT  
  2. SearchButton_TT:="Search"  
  3.  
  4. ; SHOW THE GUI  
  5. Gui, Add, Button, x575 y40 w85 h85 +Default +gSearch +Hide, Search  
  6. Gui, Add, Picture, x573 y40 w93 h96 vSearchButton gSearch, %A_ScriptDir%\search_globe.jpg  
  7. Gui, Add, Edit, x45 y40 w520 r1 vSearchTextInput Limit70, Search...  
  8. Gui, Show  
  9. OnMessage(0x200, "WM_MOUSEMOVE")  
  10. Return  
  11.  
  12.  
  13. ; FUNCTION TO HANDLE BOTH TOOLTIP AND MOUSEOVER EVENT  
  14. WM_MOUSEMOVE()  
  15. {  
  16. static CurrControl, PrevControl, _TT ; _TT is kept blank for use by the ToolTip command below.  
  17. CurrControl := A_GuiControl  
  18.  
  19. SearchButton_Over:=A_ScriptDir "\images\program\icons\search_globe_over.png"  
  20. SearchButton_Out:=A_ScriptDir "\images\program\icons\search_globe.png"  
  21.  
  22. If (CurrControl <> PrevControl and not InStr(CurrControl, " "))  
  23. {  
  24. ToolTip ; Turn off any previous tooltip.  
  25. SetTimer, DisplayToolTip, 1000  
  26. If (PrevControl="SearchButton")  
  27. GuiControl,, SearchButton, %SearchButton_Out%  
  28.  
  29. PrevControl := CurrControl  
  30. If (CurrControl="SearchButton")  
  31. GuiControl,, SearchButton, %SearchButton_Over%  
  32. }  
  33. return  
  34.  
  35. DisplayToolTip:  
  36. SetTimer, DisplayToolTip, Off  
  37. ToolTip % %CurrControl%_TT ; The leading percent sign tell it to use an expression.  
  38. SetTimer, RemoveToolTip, 3000  
  39. return  
  40.  
  41. RemoveToolTip:  
  42. SetTimer, RemoveToolTip, Off  
  43. ToolTip  
  44. return  
  45. }  
  46.  
  47. Search:  
  48. Return  
  49.  
  50. GuiClose:  
  51. ExitApp
The images I used in this GUI are: and . These have to be saved in the same folder as the AHK script.

It took me a while to get the tooltip to show until I realised you have to specify the tooltip text BEFORE the gui,show command.

The above example is used in a search form where "SearchButton" is the name of the variable (picture) to change. Note that I am using the method of hiding the input button and putting an image over it.

The code above is only really a solution to if you have one image that you are applying this mouseover effect to. With a bit more time, you could tidy up the code to do multiple images.

Note: I've updated the above code so that even if you have other objects in the GUI, hovering the mouse over other objects will no longer cause the search button to flicker.

More...?

How about having the cursor change to hand when you hover the mouse over the image:

  1. /*  
  2. IDC_ARROW := 32512  
  3. IDC_IBEAM := 32513  
  4. IDC_WAIT := 32514  
  5. IDC_CROSS := 32515  
  6. IDC_UPARROW := 32516  
  7. IDC_SIZE := 32640  
  8. IDC_ICON := 32641  
  9. IDC_SIZENWSE := 32642  
  10. IDC_SIZENESW := 32643  
  11. IDC_SIZEWE := 32644  
  12. IDC_SIZENS := 32645  
  13. IDC_SIZEALL := 32646  
  14. IDC_NO := 32648  
  15. IDC_HAND := 32649  
  16. IDC_APPSTARTING := 32650  
  17. IDC_HELP := 32651  
  18. */  
  19.  
  20. WM_MOUSEMOVE()  
  21. {  
  22. static CurrControl, PrevControl, _TT ; _TT is kept blank for use by the ToolTip command below.  
  23. CurrControl := A_GuiControl  
  24.  
  25. SearchButton_Over:=A_ScriptDir "\images\program\icons\search_globe_over.png"  
  26. SearchButton_Out:=A_ScriptDir "\images\program\icons\search_globe.png"  
  27.  
  28. If (CurrControl <> PrevControl and not InStr(CurrControl, " "))  
  29. {  
  30. ToolTip ; Turn off any previous tooltip.  
  31. SetTimer, DisplayToolTip, 1000  
  32. If (PrevControl="SearchButton")  
  33. {  
  34. GuiControl,, SearchButton, %SearchButton_Out%  
  35. RestoreCursors()  
  36. }  
  37.  
  38. PrevControl := CurrControl  
  39. If (CurrControl="SearchButton")  
  40. {  
  41. GuiControl,, SearchButton, %SearchButton_Over%  
  42. SetSystemCursor("IDC_HAND")  
  43. }  
  44. }  
  45. return  
  46.  
  47. DisplayToolTip:  
  48. SetTimer, DisplayToolTip, Off  
  49. ToolTip % %CurrControl%_TT ; The leading percent sign tell it to use an expression.  
  50. SetTimer, RemoveToolTip, 3000  
  51. return  
  52.  
  53. RemoveToolTip:  
  54. SetTimer, RemoveToolTip, Off  
  55. ToolTip  
  56. return  
  57. }  
  58.  
  59. SetSystemCursor( Cursor = "", cx = 0, cy = 0 )  
  60. {  
  61. BlankCursor := 0, SystemCursor := 0, FileCursor := 0 ; init  
  62.  
  63. SystemCursors = 32512IDC_ARROW, 32513IDC_IBEAM, 32514IDC_WAIT, 32515IDC_CROSS, 32516IDC_UPARROW, 32640IDC_SIZE, 32641IDC_ICON, 32642IDC_SIZENWSE, 32643IDC_SIZENESW, 32644IDC_SIZEWE, 32645IDC_SIZENS, 32646IDC_SIZEALL, 32648IDC_NO, 32649IDC_HAND, 32650IDC_APPSTARTING, 32651IDC_HELP  
  64.  
  65. If Cursor = ; empty, so create blank cursor  
  66. {  
  67. VarSetCapacity( AndMask, 32*4, 0xFF ), VarSetCapacity( XorMask, 32*4, 0 )  
  68. BlankCursor = 1 ; flag for later  
  69. }  
  70. Else If SubStr( Cursor,1,4 ) = "IDC_" ; load system cursor  
  71. {  
  72. Loop, Parse, SystemCursors, `,  
  73. {  
  74. CursorName := SubStr( A_Loopfield, 6, 15 ) ; get the cursor name, no trailing space with substr  
  75. CursorID := SubStr( A_Loopfield, 1, 5 ) ; get the cursor id  
  76. SystemCursor = 1  
  77. If ( CursorName = Cursor )  
  78. {  
  79. CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )  
  80. Break  
  81. }  
  82. }  
  83. If CursorHandle = ; invalid cursor name given  
  84. {  
  85. Msgbox,, SetCursor, Error: Invalid cursor name  
  86. CursorHandle = Error  
  87. }  
  88. }  
  89. Else If FileExist( Cursor )  
  90. {  
  91. SplitPath, Cursor,,, Ext ; auto-detect type  
  92. If Ext = ico  
  93. uType := 0x1  
  94. Else If Ext in cur,ani  
  95. uType := 0x2  
  96. Else ; invalid file ext  
  97. {  
  98. Msgbox,, SetCursor, Error: Invalid file type  
  99. CursorHandle = Error  
  100. }  
  101. FileCursor = 1  
  102. }  
  103. Else  
  104. {  
  105. Msgbox,, SetCursor, Error: Invalid file path or cursor name  
  106. CursorHandle = Error ; raise for later  
  107. }  
  108. If CursorHandle != Error  
  109. {  
  110. Loop, Parse, SystemCursors, `,  
  111. {  
  112. If BlankCursor = 1  
  113. {  
  114. Type = BlankCursor  
  115. %Type%%A_Index% := DllCall( "CreateCursor", Uint,0, Int,0, Int,0, Int,32, Int,32, Uint,&AndMask, Uint,&XorMask )  
  116. CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )  
  117. DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )  
  118. }  
  119. Else If SystemCursor = 1  
  120. {  
  121. Type = SystemCursor  
  122. CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )  
  123. %Type%%A_Index% := DllCall( "CopyImage", Uint,CursorHandle, Uint,0x2, Int,cx, Int,cy, Uint,0 )  
  124. CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )  
  125. DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )  
  126. }  
  127. Else If FileCursor = 1  
  128. {  
  129. Type = FileCursor  
  130. %Type%%A_Index% := DllCall( "LoadImageA", UInt,0, Str,Cursor, UInt,uType, Int,cx, Int,cy, UInt,0x10 )  
  131. DllCall( "SetSystemCursor", Uint,%Type%%A_Index%, Int,SubStr( A_Loopfield, 1, 5 ) )  
  132. }  
  133. }  
  134. }  
  135. }  
  136.  
  137. RestoreCursors()  
  138. {  
  139. SPI_SETCURSORS := 0x57  
  140. DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 )  
  141. }

In this code, the IDC stuff commented out at the beginning is for your reference. You need to include the setsystemcursor() and restoreCursors() functions somewhere in your script.


Update: 07 July 2011: For Jose Luis

The images I used in this GUI are: and . These have to be saved in the same folder as the AHK script. Well they don't have to, I've just put A_ScriptDir and then the files but for my own program, I put them in folders.
Here's the whole code to make a gui with 1 image mouseover:
  1. ;  
  2. ; AutoHotkey Version: 1.x  
  3. ; Language: English  
  4. ; Platform: Win9x/NT  
  5. ; Author: A.N.Other  
  6. ;  
  7. ; Script Function:  
  8. ; Template script (you can customize this template by editing "ShellNew\Template.ahk" in your Windows folder)  
  9. ;  
  10.  
  11. #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.  
  12. SendMode Input ; Recommended for new scripts due to its superior speed and reliability.  
  13. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.  
  14.  
  15.  
  16. ; SET TOOLTIP TEXT  
  17. SearchButton_TT:="Search"  
  18.  
  19. ; SHOW THE GUI  
  20. Gui, Color, FFFFFF  
  21. Gui, Font, s16, Verdana,  
  22. Gui, Add, Button, x575 y40 w85 h85 +Default +gSearch +Hide, Search  
  23. Gui, Add, Picture, x573 y40 w93 h96 vSearchButton gSearch, %A_ScriptDir%\search_globe.png  
  24. Gui, Add, Edit, x45 y40 w520 r1 vSearchTextInput Limit70, Search...  
  25. Gui, Show  
  26. OnMessage(0x200, "WM_MOUSEMOVE")  
  27.  
  28. Return  
  29.  
  30. ; FUNCTION TO HANDLE BOTH TOOLTIP AND MOUSEOVER EVENT  
  31. WM_MOUSEMOVE()  
  32. {  
  33. static CurrControl, PrevControl, _TT ; _TT is kept blank for use by the ToolTip command below.  
  34. CurrControl := A_GuiControl  
  35.  
  36. SearchButton_Over:=A_ScriptDir "\search_globe_over.png"  
  37. SearchButton_Out:=A_ScriptDir "\search_globe.png"  
  38.  
  39. If (CurrControl <> PrevControl and not InStr(CurrControl, " "))  
  40. {  
  41. ToolTip ; Turn off any previous tooltip.  
  42. SetTimer, DisplayToolTip, 1000  
  43. If (PrevControl="SearchButton")  
  44. {  
  45. GuiControl,, SearchButton, %SearchButton_Out%  
  46. RestoreCursors()  
  47. }  
  48.  
  49. PrevControl := CurrControl  
  50. If (CurrControl="SearchButton")  
  51. {  
  52. GuiControl,, SearchButton, %SearchButton_Over%  
  53. SetSystemCursor("IDC_HAND")  
  54. }  
  55. }  
  56. return  
  57.  
  58. DisplayToolTip:  
  59. SetTimer, DisplayToolTip, Off  
  60. ToolTip % %CurrControl%_TT ; The leading percent sign tell it to use an expression.  
  61. SetTimer, RemoveToolTip, 3000  
  62. return  
  63.  
  64. RemoveToolTip:  
  65. SetTimer, RemoveToolTip, Off  
  66. ToolTip  
  67. return  
  68. }  
  69.  
  70. ; ==================================================================================  
  71. ; DON'T EDIT THESE FUNCTIONS BELOW (I have no idea how they work only that they do)  
  72.  
  73. SetCursor(pShape, pCtrl="") {  
  74. return SetCursor_(pShape, pCtrl, 0, 0)  
  75. }  
  76.  
  77. SetCursor_(wparam, lparam, msg, hwnd) {  
  78. static WM_SETCURSOR := 0x20, WM_MOUSEMOVE := 0x200  
  79. static APPSTARTING := 32650,HAND := 32649 ,ARROW := 32512,CROSS := 32515 ,IBEAM := 32513 ,NO := 32648 ,SIZE := 32640 ,SIZEALL := 32646 ,SIZENESW := 32643 ,SIZENS := 32645 ,SIZENWSE := 32642 ,SIZEWE := 32644 ,UPARROW := 32516 ,WAIT := 32514  
  80. static SIZEWE_BIG := 32653, SIZEALL_BIG := 32654, SIZEN_BIG := 32655, SIZES_BIG := 32656, SIZEW_BIG := 32657, SIZEE_BIG := 32658, SIZENW_BIG := 32659, SIZENE_BIG := 32660, SIZESW_BIG := 32661, SIZESE_BIG := 32662  
  81. static hover, curOld=32512, cursor, ctrls="`n", init  
  82.  
  83. if !init  
  84. init := 1, OnMessage(WM_SETCURSOR, "SetCursor_"), OnMessage(WM_MOUSEMOVE, "SetCursor_")  
  85.  
  86. if A_Gui =  
  87. {  
  88. if wparam is not Integer  
  89. If InStr( wparam, ".cur" ) || InStr( wparam, ".ani" ) { ;LoadCursorFromFile  
  90. IfNotExist, % WPARAM ; verify existance  
  91. return  
  92. cursor := DllCall("LoadCursorFromFile", "Str", WPARAM)  
  93. }  
  94. Else cursor := DllCall("LoadCursor", "Uint", 0, "Int", %WPARAM%, "Uint")  
  95.  
  96. if lparam =  
  97. curOld := cursor  
  98. else ctrls .= lparam "=" cursor "`n"  
  99. }  
  100.  
  101. If (msg = WM_SETCURSOR)  
  102. ifEqual, hover, 1, return 1  
  103.  
  104. if (msg = WM_MOUSEMOVE)  
  105. {  
  106. MouseGetPos, ,,,c  
  107. If j := InStr(ctrls, "`n" c "=")  
  108. {  
  109. hover := true,  
  110. j += 2+StrLen(c)  
  111. j := SubStr(ctrls, j, InStr(ctrls, "`n", 0, j)-j+1)  
  112. DllCall("SetCursor", "uint",j)  
  113. }  
  114. else DllCall("SetCursor", "uint", curOld), hover := ""  
  115. }  
  116.  
  117. }  
  118.  
  119. SetSystemCursor( Cursor = "", cx = 0, cy = 0 )  
  120. {  
  121. BlankCursor := 0, SystemCursor := 0, FileCursor := 0 ; init  
  122.  
  123. SystemCursors = 32512IDC_ARROW,32513IDC_IBEAM,32514IDC_WAIT,32515IDC_CROSS,32516IDC_UPARROW,32640IDC_SIZE,32641IDC_ICON,32642IDC_SIZENWSE,32643IDC_SIZENESW,32644IDC_SIZEWE,32645IDC_SIZENS,32646IDC_SIZEALL,32648IDC_NO,32649IDC_HAND,32650IDC_APPSTARTING,32651IDC_HELP  
  124.  
  125. If Cursor = ; empty, so create blank cursor  
  126. {  
  127. VarSetCapacity( AndMask, 32*4, 0xFF ), VarSetCapacity( XorMask, 32*4, 0 )  
  128. BlankCursor = 1 ; flag for later  
  129. }  
  130. Else If SubStr( Cursor,1,4 ) = "IDC_" ; load system cursor  
  131. {  
  132. Loop, Parse, SystemCursors, `,  
  133. {  
  134. CursorName := SubStr( A_Loopfield, 6, 15 ) ; get the cursor name, no trailing space with substr  
  135. CursorID := SubStr( A_Loopfield, 1, 5 ) ; get the cursor id  
  136. SystemCursor = 1  
  137. If ( CursorName = Cursor )  
  138. {  
  139. CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )  
  140. Break  
  141. }  
  142. }  
  143. If CursorHandle = ; invalid cursor name given  
  144. {  
  145. Msgbox,, SetCursor, Error: Invalid cursor name  
  146. CursorHandle = Error  
  147. }  
  148. }  
  149. Else If FileExist( Cursor )  
  150. {  
  151. SplitPath, Cursor,,, Ext ; auto-detect type  
  152. If Ext = ico  
  153. uType := 0x1  
  154. Else If Ext in cur,ani  
  155. uType := 0x2  
  156. Else ; invalid file ext  
  157. {  
  158. Msgbox,, SetCursor, Error: Invalid file type  
  159. CursorHandle = Error  
  160. }  
  161. FileCursor = 1  
  162. }  
  163. Else  
  164. {  
  165. Msgbox,, SetCursor, Error: Invalid file path or cursor name  
  166. CursorHandle = Error ; raise for later  
  167. }  
  168. If CursorHandle != Error  
  169. {  
  170. Loop, Parse, SystemCursors, `,  
  171. {  
  172. If BlankCursor = 1  
  173. {  
  174. Type = BlankCursor  
  175. %Type%%A_Index% := DllCall( "CreateCursor", Uint,0, Int,0, Int,0, Int,32, Int,32, Uint,&AndMask, Uint,&XorMask )  
  176. CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )  
  177. DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )  
  178. }  
  179. Else If SystemCursor = 1  
  180. {  
  181. Type = SystemCursor  
  182. CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )  
  183. %Type%%A_Index% := DllCall( "CopyImage", Uint,CursorHandle, Uint,0x2, Int,cx, Int,cy, Uint,0 )  
  184. CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )  
  185. DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )  
  186. }  
  187. Else If FileCursor = 1  
  188. {  
  189. Type = FileCursor  
  190. %Type%%A_Index% := DllCall( "LoadImageA", UInt,0, Str,Cursor, UInt,uType, Int,cx, Int,cy, UInt,0x10 )  
  191. DllCall( "SetSystemCursor", Uint,%Type%%A_Index%, Int,SubStr( A_Loopfield, 1, 5 ) )  
  192. }  
  193. }  
  194. }  
  195. }  
  196.  
  197. RestoreCursors()  
  198. {  
  199. SPI_SETCURSORS := 0x57  
  200. DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 )  
  201. }  
  202.  
  203. ; ==================================================================================  
  204. ; GUI FUNCTIONS  
  205.  
  206. Search:  
  207. MsgBox, Searching...  
  208. Return  
  209.  
  210. GuiClose:  
  211. Exitapp

The images I used in the search GUI above are: and . These have to be saved in the same folder as the AHK script. Well they don't have to, I've just put A_ScriptDir and then the files but for my own program, I put them in folders.

These functions are documented in the autohotkey forums at http://www.autohotkey.com/forum/topic35600-15.html

Enjoy!



Article Comment (1)

Thursday, 7th July 2011
2 Votes
Gravatar for Joel
Joel
Update for Jose Luis: I've amended the code, the reason was quite pivotal considering I'd missed the following out:
OnMessage(0x200, "WM_MOUSEMOVE")

Thanks for your email and hope this helps. To be honest, I have switched to using cwebpage.dll to produce internal HTML pages (which support IE functions) and do the mouseovers with that. I'm then learning COM scripts which can even do more.


Recent Comments

Gravatar for Art
Oracle: order by subquery missing right parenthesis
Hello, what if I would like to add rownum to that code, but in my case it's all is subquery? How can I do this ?

20 Jan


Gravatar for Robert
CharIndex Reverse - find occurrence starting from end of string in TSQL
Very helpful thanks! This worked for me as well, and is a little shorter. Not sure if there are drawbacks. SELECT RIGHT(@Haystack,CHARINDEX(@Delimiter,REVERSE(@Haystack))-LEN(@Delimiter))

29 Dec


Gravatar for Translation

27 Dec


Gravatar for Tibbe
JComments 2.3.0 with ReCaptcha in Joomla 2.5.x
Hi there, This looks like a great solution to get rid of spam comments. How to integrate this in Joomla 3.x? Step 2 I did in settings.xml, but no result in frontend. Kind Regards, Tibbe

16 Dec


Gravatar for sach|n
SSRS Repeat Headers in PDF Report
Yes its working for me..thnx Joel.

7 Oct