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



Comments
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.