Monday, December 22, 2014
   
Text Size
Login

Add Image Mouseover effect in AutoHotkey GUI

 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 @nowhere.com> 
  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!

Comments   

# Joel Thu, 7th July 2011
Update for Jose Luis: I've amended the code, the reason was quite pivotal considering I'd missed the following out:
Code: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.
Like | Dislike | +1 Reply | Reply with quote | Quote
Add Comment

Name:

Email:

Website:

Message:


Latest Posts

  • Basic Android App using Google Maps and Current Location

    • Wed 17-Dec-14
      Is that how it's spelt? setContentVie( "View". If not try going to build and "clean project". Also ...
      Joel L.  
    • Tue 16-Dec-14
      I have problem in "cannot resolved R" " setContentVie(R .layout.activit y_maps);" :cry: How to solve ...
      LucasR
  • Migrate Joomla! 1.5.x to 2.5.x+

    • Thu 18-Dec-14
      Interesting report LLiSEIL! I'll definitely have to review it when Joomla 3.5 comes out. Error 1: is ...
      Joel L.  
    • Tue 16-Dec-14
      * Categories: - duplicates, I suppose from the multiple times I launched the script. - love the notes ...
      LLiSEIL  
    • Tue 16-Dec-14
      SQL ERror 3 > -- Step 2) Import articles from J15 and insert as articles in J30 INSERT INTO `newbase_j25`.d ...
      LLiSEIL