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
- ; 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
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; ; 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!