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:


    ; SET TOOLTIP TEXT
    SearchButton_TT:="Search"

    ; SHOW THE GUI
    Gui, Add, Button, x575 y40 w85 h85 +Default +gSearch +Hide, Search
    Gui, Add, Picture, x573 y40 w93 h96 vSearchButton gSearch, %A_ScriptDir%\search_globe.jpg
    Gui, Add, Edit, x45 y40 w520 r1 vSearchTextInput Limit70, Search...
    Gui, Show
    OnMessage(0x200, "WM_MOUSEMOVE")
    Return


    ; FUNCTION TO HANDLE BOTH TOOLTIP AND MOUSEOVER EVENT
WM_MOUSEMOVE()
{
    static CurrControl, PrevControl, _TT  ; _TT is kept blank for use by the ToolTip command below.
    CurrControl := A_GuiControl

    SearchButton_Over:=A_ScriptDir "\images\program\icons\search_globe_over.png"
    SearchButton_Out:=A_ScriptDir "\images\program\icons\search_globe.png"

    If (CurrControl <> PrevControl and not InStr(CurrControl, " "))
    {
        ToolTip  ; Turn off any previous tooltip.
        SetTimer, DisplayToolTip, 1000
        If (PrevControl="SearchButton")
            GuiControl,, SearchButton, %SearchButton_Out%

        PrevControl := CurrControl
        If (CurrControl="SearchButton")
            GuiControl,, SearchButton, %SearchButton_Over%
    }
    return

    DisplayToolTip:
    SetTimer, DisplayToolTip, Off
    ToolTip % %CurrControl%_TT  ; The leading percent sign tell it to use an expression.
    SetTimer, RemoveToolTip, 3000
    return

    RemoveToolTip:
    SetTimer, RemoveToolTip, Off
    ToolTip
    return
}

Search:
Return

GuiClose:
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:

/*
IDC_ARROW := 32512
IDC_IBEAM := 32513
IDC_WAIT := 32514
IDC_CROSS := 32515
IDC_UPARROW := 32516
IDC_SIZE := 32640
IDC_ICON := 32641
IDC_SIZENWSE := 32642
IDC_SIZENESW := 32643
IDC_SIZEWE := 32644
IDC_SIZENS := 32645
IDC_SIZEALL := 32646
IDC_NO := 32648
IDC_HAND := 32649
IDC_APPSTARTING := 32650
IDC_HELP := 32651
*/

WM_MOUSEMOVE()
{
    static CurrControl, PrevControl, _TT  ; _TT is kept blank for use by the ToolTip command below.
    CurrControl := A_GuiControl

    SearchButton_Over:=A_ScriptDir "\images\program\icons\search_globe_over.png"
    SearchButton_Out:=A_ScriptDir "\images\program\icons\search_globe.png"

    If (CurrControl <> PrevControl and not InStr(CurrControl, " "))
    {
        ToolTip  ; Turn off any previous tooltip.
        SetTimer, DisplayToolTip, 1000
        If (PrevControl="SearchButton")
	{
		GuiControl,, SearchButton, %SearchButton_Out%
		RestoreCursors()
	}

        PrevControl := CurrControl
        If (CurrControl="SearchButton")
	{
		GuiControl,, SearchButton, %SearchButton_Over%
		SetSystemCursor("IDC_HAND")
	}
    }
    return

    DisplayToolTip:
    SetTimer, DisplayToolTip, Off
    ToolTip % %CurrControl%_TT  ; The leading percent sign tell it to use an expression.
    SetTimer, RemoveToolTip, 3000
    return

    RemoveToolTip:
    SetTimer, RemoveToolTip, Off
    ToolTip
    return
}

SetSystemCursor( Cursor = "", cx = 0, cy = 0 )
{
   BlankCursor := 0, SystemCursor := 0, FileCursor := 0 ; init

   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

   If Cursor = ; empty, so create blank cursor
   {
      VarSetCapacity( AndMask, 32*4, 0xFF ), VarSetCapacity( XorMask, 32*4, 0 )
      BlankCursor = 1 ; flag for later
   }
   Else If SubStr( Cursor,1,4 ) = "IDC_" ; load system cursor
   {
      Loop, Parse, SystemCursors, `,
      {
         CursorName := SubStr( A_Loopfield, 6, 15 ) ; get the cursor name, no trailing space with substr
         CursorID := SubStr( A_Loopfield, 1, 5 ) ; get the cursor id
         SystemCursor = 1
         If ( CursorName = Cursor )
         {
            CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )
            Break
         }
      }
      If CursorHandle = ; invalid cursor name given
      {
         Msgbox,, SetCursor, Error: Invalid cursor name
         CursorHandle = Error
      }
   }
   Else If FileExist( Cursor )
   {
      SplitPath, Cursor,,, Ext ; auto-detect type
      If Ext = ico
         uType := 0x1
      Else If Ext in cur,ani
         uType := 0x2
      Else ; invalid file ext
      {
         Msgbox,, SetCursor, Error: Invalid file type
         CursorHandle = Error
      }
      FileCursor = 1
   }
   Else
   {
      Msgbox,, SetCursor, Error: Invalid file path or cursor name
      CursorHandle = Error ; raise for later
   }
   If CursorHandle != Error
   {
      Loop, Parse, SystemCursors, `,
      {
         If BlankCursor = 1
         {
            Type = BlankCursor
            %Type%%A_Index% := DllCall( "CreateCursor", Uint,0, Int,0, Int,0, Int,32, Int,32, Uint,&AndMask, Uint,&XorMask )
            CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
            DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
         }
         Else If SystemCursor = 1
         {
            Type = SystemCursor
            CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )
            %Type%%A_Index% := DllCall( "CopyImage", Uint,CursorHandle, Uint,0x2, Int,cx, Int,cy, Uint,0 )
            CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
            DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
         }
         Else If FileCursor = 1
         {
            Type = FileCursor
            %Type%%A_Index% := DllCall( "LoadImageA", UInt,0, Str,Cursor, UInt,uType, Int,cx, Int,cy, UInt,0x10 )
            DllCall( "SetSystemCursor", Uint,%Type%%A_Index%, Int,SubStr( A_Loopfield, 1, 5 ) )
         }
      }
   }
}

RestoreCursors()
{
   SPI_SETCURSORS := 0x57
   DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 )
}

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:
;
; AutoHotkey Version: 1.x
; Language:       English
; Platform:       Win9x/NT
; Author:         A.N.Other <This email address is being protected from spambots. You need JavaScript enabled to view it.>
;
; Script Function:
;	Template script (you can customize this template by editing "ShellNew\Template.ahk" in your Windows folder)
;

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.


    ; SET TOOLTIP TEXT
    SearchButton_TT:="Search"

    ; SHOW THE GUI
    Gui, Color, FFFFFF
	Gui, Font, s16, Verdana,
	Gui, Add, Button, x575 y40 w85 h85 +Default +gSearch +Hide, Search
	Gui, Add, Picture, x573 y40 w93 h96 vSearchButton gSearch, %A_ScriptDir%\search_globe.png
	Gui, Add, Edit, x45 y40 w520 r1 vSearchTextInput Limit70, Search...
	Gui, Show
    	OnMessage(0x200, "WM_MOUSEMOVE")

Return

    ; FUNCTION TO HANDLE BOTH TOOLTIP AND MOUSEOVER EVENT
WM_MOUSEMOVE()
{
    static CurrControl, PrevControl, _TT  ; _TT is kept blank for use by the ToolTip command below.
    CurrControl := A_GuiControl

    SearchButton_Over:=A_ScriptDir "\search_globe_over.png"
    SearchButton_Out:=A_ScriptDir "\search_globe.png"

    If (CurrControl <> PrevControl and not InStr(CurrControl, " "))
    {
        ToolTip  ; Turn off any previous tooltip.
        SetTimer, DisplayToolTip, 1000
        If (PrevControl="SearchButton")
	{
		GuiControl,, SearchButton, %SearchButton_Out%
		RestoreCursors()
	}

        PrevControl := CurrControl
        If (CurrControl="SearchButton")
	{
		GuiControl,, SearchButton, %SearchButton_Over%
		SetSystemCursor("IDC_HAND")
	}
    }
    return

    DisplayToolTip:
    SetTimer, DisplayToolTip, Off
    ToolTip % %CurrControl%_TT  ; The leading percent sign tell it to use an expression.
    SetTimer, RemoveToolTip, 3000
    return

    RemoveToolTip:
    SetTimer, RemoveToolTip, Off
    ToolTip
    return
}

; ==================================================================================
; DON'T EDIT THESE FUNCTIONS BELOW (I have no idea how they work only that they do)

SetCursor(pShape, pCtrl="") {
   return SetCursor_(pShape, pCtrl, 0, 0)
}

SetCursor_(wparam, lparam, msg, hwnd) {
   static WM_SETCURSOR := 0x20, WM_MOUSEMOVE := 0x200
   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
   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
   static hover, curOld=32512, cursor, ctrls="`n", init

   if !init
      init := 1, OnMessage(WM_SETCURSOR, "SetCursor_"),  OnMessage(WM_MOUSEMOVE, "SetCursor_")

   if A_Gui =
   {
      if wparam is not Integer
            If InStr( wparam, ".cur" ) || InStr( wparam, ".ani" ) {   ;LoadCursorFromFile
                 IfNotExist, % WPARAM  ; verify existance
                    return
                 cursor := DllCall("LoadCursorFromFile", "Str", WPARAM)
            }
            Else cursor := DllCall("LoadCursor", "Uint", 0, "Int", %WPARAM%, "Uint")

      if lparam =
            curOld := cursor
      else  ctrls .= lparam "=" cursor "`n"
   }

   If (msg = WM_SETCURSOR)
      ifEqual, hover, 1,   return 1

   if (msg = WM_MOUSEMOVE)
   {
      MouseGetPos, ,,,c
      If j := InStr(ctrls, "`n" c "=")
      {
         hover := true,
         j += 2+StrLen(c)
         j := SubStr(ctrls, j, InStr(ctrls, "`n", 0, j)-j+1)
         DllCall("SetCursor", "uint",j)
      }
      else DllCall("SetCursor", "uint", curOld), hover := ""
   }

}

SetSystemCursor( Cursor = "", cx = 0, cy = 0 )
{
   BlankCursor := 0, SystemCursor := 0, FileCursor := 0 ; init

   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

   If Cursor = ; empty, so create blank cursor
   {
      VarSetCapacity( AndMask, 32*4, 0xFF ), VarSetCapacity( XorMask, 32*4, 0 )
      BlankCursor = 1 ; flag for later
   }
   Else If SubStr( Cursor,1,4 ) = "IDC_" ; load system cursor
   {
      Loop, Parse, SystemCursors, `,
      {
         CursorName := SubStr( A_Loopfield, 6, 15 ) ; get the cursor name, no trailing space with substr
         CursorID := SubStr( A_Loopfield, 1, 5 ) ; get the cursor id
         SystemCursor = 1
         If ( CursorName = Cursor )
         {
            CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )
            Break
         }
      }
      If CursorHandle = ; invalid cursor name given
      {
         Msgbox,, SetCursor, Error: Invalid cursor name
         CursorHandle = Error
      }
   }
   Else If FileExist( Cursor )
   {
      SplitPath, Cursor,,, Ext ; auto-detect type
      If Ext = ico
         uType := 0x1
      Else If Ext in cur,ani
         uType := 0x2
      Else ; invalid file ext
      {
         Msgbox,, SetCursor, Error: Invalid file type
         CursorHandle = Error
      }
      FileCursor = 1
   }
   Else
   {
      Msgbox,, SetCursor, Error: Invalid file path or cursor name
      CursorHandle = Error ; raise for later
   }
   If CursorHandle != Error
   {
      Loop, Parse, SystemCursors, `,
      {
         If BlankCursor = 1
         {
            Type = BlankCursor
            %Type%%A_Index% := DllCall( "CreateCursor", Uint,0, Int,0, Int,0, Int,32, Int,32, Uint,&AndMask, Uint,&XorMask )
            CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
            DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
         }
         Else If SystemCursor = 1
         {
            Type = SystemCursor
            CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )
            %Type%%A_Index% := DllCall( "CopyImage", Uint,CursorHandle, Uint,0x2, Int,cx, Int,cy, Uint,0 )
            CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
            DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
         }
         Else If FileCursor = 1
         {
            Type = FileCursor
            %Type%%A_Index% := DllCall( "LoadImageA", UInt,0, Str,Cursor, UInt,uType, Int,cx, Int,cy, UInt,0x10 )
            DllCall( "SetSystemCursor", Uint,%Type%%A_Index%, Int,SubStr( A_Loopfield, 1, 5 ) )
         }
      }
   }
}

RestoreCursors()
{
   SPI_SETCURSORS := 0x57
   DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 )
}

; ==================================================================================
; GUI FUNCTIONS

Search:
	MsgBox, Searching...
Return

GuiClose:
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!

Add comment


Send

Comments   

+2 Joel L Thursday, 7th July 2011, 7:02 pm
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.