Update 2008/09/10 - Wrapper function released. (See end of post).
The first thing is decide what kind of cursor to use - a system cursor, or a cursor loaded from a file? It is also possible to load a cursor from within a script, see Crazy Scripting : Include an Icon in your script.
Using a system cursor
These are our cursor IDs:
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
To load a system cursor use LoadCursor, which returns a handle to use in SetSystemCursor. Here I've used IDC_SIZEALL:
CursorHandle := DllCall( "LoadCursor", Uint,0, Int,IDC_SIZEALL )
Loading a cursor from a file
If you want to load a cursor from a file, use LoadCursorFromFile instead. You can also load an icon file here:
Cursor = %A_ScriptDir%\mycursor.ani CursorHandle := DllCall( "LoadCursorFromFile", Str,Cursor )
Size of cursor
We can change the size of the cursor with CopyImage, although this method stretches it so the end look may not be satisfactory. This step is optional:
; uType: IMAGE_BITMAP := 0x0 IMAGE_CURSOR := 0x2 IMAGE_ICON := 0x1 ; Size: cx := 32, cy := cx ; fuFlags: LR_COPYFROMRESOURCE := 0x4000 CursorHandle := DllCall( "CopyImage", uint,CursorHandle, uint,IMAGE_CURSOR, int,cx, int,cy, uint,0 )
We can use LoadImage instead of LoadCursorFromFile to load non-standard size icons and cursors. I used this method to load a 48x48 icon when my system is set to 32x32. I also tried this with multi icon and it seems to always load the largest icon.
Note: LoadCursorFromFile will load other size icons and cursors but it seems to force the system settings onto it as it loads. The result after a resize via CopyImage isn't as nice even with the LR_COPYFROMRESOURCE option.
Image = %A_ScriptDir%\mymulti.ico ; uType: IMAGE_BITMAP := 0x0 IMAGE_CURSOR := 0x2 IMAGE_ICON := 0x1 ; Size: cx := 48, cy := cx ; fuLoad: LR_COLOR := 0x2 LR_CREATEDIBSECTION := 0x2000 LR_DEFAULTSIZE := 0x40 LR_LOADFROMFILE := 0x10 LR_LOADMAP3DCOLORS := 0x1000 CursorHandle := DllCall( "LoadImageA", UInt,0, Str,Image, UInt,IMAGE_ICON, Int,cx, Int,cy, UInt,0x10 )
Loading from a DLL or EXE
It may also be possible to load a cursor or icon from a DLL or EXE file. Here we need GetModuleHandle to get a handle for LoadImage, and MAKEINTRESOURCE to load a resource by ordinal. If anyone knows how to use MAKEINTRESOURCE macro within DllCall do post.
; uType:
IMAGE_BITMAP := 0x0
IMAGE_CURSOR := 0x2
IMAGE_ICON := 0x1
; Size:
cx := 48, cy := cx
; fuLoad:
LR_COLOR := 0x2
LR_CREATEDIBSECTION := 0x2000
LR_DEFAULTSIZE := 0x40
LR_LOADFROMFILE := 0x10
LR_LOADMAP3DCOLORS := 0x1000
Module = %A_WinDir%\SYSTEM32\SHELL32.DLL
ModuleHandle := DllCall("GetModuleHandleA", Str,Module)
CursorHandle := DllCall( "LoadImageA", Uint,ModuleHandle, Str,Cursor, Uint,IMAGE_ICON, Int,cx, Int,cy, UInt,0x10 )Replacing the cursors
Now that we've loaded a cursor, the next step is to loop through a list of system cursors to replace all of them:
Cursors = 32512,32513,32514,32515,32516,32640,32641,32642,32643,32644,32645,32646,32648,32649,32650,32651
Loop, Parse, Cursors, `,
{
DllCall( "SetSystemCursor", Uint,CursorHandle, Int,A_Loopfield )
}
Restoring system cursors
To restore system cursors use SystemParametersInfo/SPI_SETCURSORS:
SPI_SETCURSORS := 0x57 DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 ) ; Reload the system cursors
Example script: The following changes the cursor while the MButton is down, and restores it on release.
#SingleInstance Force
~MButton::SetSystemCursor()
~MButton Up::RestoreCursors()
SetSystemCursor()
{
IDC_SIZEALL := 32646
CursorHandle := DllCall( "LoadCursor", Uint,0, Int,IDC_SIZEALL )
Cursors = 32512,32513,32514,32515,32516,32640,32641,32642,32643,32644,32645,32646,32648,32649,32650,32651
Loop, Parse, Cursors, `,
{
DllCall( "SetSystemCursor", Uint,CursorHandle, Int,A_Loopfield )
}
}
RestoreCursors()
{
SPI_SETCURSORS := 0x57
DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 )
}Wrapper function
This covers nearly everything in a single function. I've left out RestoreCursors as I think it should be seperate.
SetSystemCursor( File path or cursor name, Width, Height )
Parameter 1 is file path or cursor name, e.g. IDC_SIZEALL. If this is omitted it will hide the cursor.
Parameters 2 and 3 are the desired width and height of cursor. Omit these to use the default size, e.g. loading a 48x48 cursor will display as 48x48.
Changelog
2008/09/13 - Set cursor now shows everywhere bar apps that set their own cursor
2008/09/10 - Wrapper function released
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 )
}



Sign In
Create Account
Last active: 
Back to top