How to change the system cursor??

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
jly
Posts: 89
Joined: 30 Sep 2020, 06:06

How to change the system cursor??

08 May 2021, 00:00

Changing the system cursor
https://autohotkey.com/board/topic/32608-changing-the-system-cursor/

I have found the thread to change the system cursor, but the new cursor is not the same to the old.


Execute the following code, press the F1 key continuously, observe the changes of the cursor,
the cursor of the new arrow shape is a little fuzzy
Cursor__shape.png
Cursor__shape.png (7.12 KiB) Viewed 740 times

Code: Select all


F1::
	if(flag := !flag)
		SetSystemCursor( "IDC_ARROW")
	else
		RestoreCursors()
return



SetSystemCursor(Cursor) {
   ; Cursor has to contain the name of a system cursor (IDC_...)
   ; IDC_ICON and IDC_SIZE are "Obsolete for applications marked version 4.0 or later."
   ; -> http://msdn.microsoft.com/en-us/library/ms648391%28v=vs.85%29.aspx
   ; and not listed in the OCR_... values of the SetSystemCursor function.
   ; -> http://msdn.microsoft.com/en-us/library/ms648395%28v=vs.85%29.aspx
   Static
   Initialized := False
   SystemCursors := "32512IDC_ARROW|32513IDC_IBEAM|32514IDC_WAIT|32515IDC_CROSS|"
                  . "32516IDC_UPARROW|32642IDC_SIZENWSE|"
                  . "32643IDC_SIZENESW|32644IDC_SIZEWE|32645IDC_SIZENS|32646IDC_SIZEALL|"
                  . "32648IDC_NO|32649IDC_HAND|32650IDC_APPSTARTING|32651IDC_HELP"
   If !(Initialized) { ; load system cursors only once
      Loop, Parse, SystemCursors, |
      {
         CID := SubStr(A_LoopField, 1, 5)
         CNA := SubStr(A_LoopField, 6)
         HC%CNA% := DllCall("LoadCursor", "UInt", 0, "Int", CID)
      }
      Initialized := True
   }
   If !(HC%Cursor%) {
      Msgbox, 0, SetSystemCursor, Error: Invalid cursor name %Cursor%
      Return False
   }
   Loop, Parse, SystemCursors, |
   {
      CID := SubStr(A_LoopField, 1, 5)
      HCUR := DllCall("CopyIcon", "UInt" , HC%Cursor%)
      DllCall("SetSystemCursor", "UInt", HCUR, "Int", CID)
   }
   Return True
}




;SetSystemCursor( Cursor = "", cx = 0, cy = 0 )
SetSystemCursor2( Cursor = "", cx := 64, cy := 64 )
{
	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 )
}


esc::
RestoreCursors()
ExitApp
return

teadrinker
Posts: 4325
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to change the system cursor??

08 May 2021, 06:10

Anyway dll calls are incorrect. Should be like this:

Code: Select all

$F1:: ReplaceSystemCursors((t := !t) ? "IDC_ARROW" : "")

ReplaceSystemCursors(IDC = "") ; IDC must be a cursor name like "IDC_CROSS" or cursor handle
{
   static IMAGE_CURSOR := 2, SPI_SETCURSORS := 0x57
        , exitFunc := Func("ReplaceSystemCursors").Bind("")
        , setOnExit := false
        , SysCursors := { IDC_APPSTARTING: 32650
                        , IDC_ARROW      : 32512
                        , IDC_CROSS      : 32515
                        , IDC_HAND       : 32649
                        , IDC_HELP       : 32651
                        , IDC_IBEAM      : 32513
                        , IDC_NO         : 32648
                        , IDC_SIZEALL    : 32646
                        , IDC_SIZENESW   : 32643
                        , IDC_SIZENWSE   : 32642
                        , IDC_SIZEWE     : 32644
                        , IDC_SIZENS     : 32645 
                        , IDC_UPARROW    : 32516
                        , IDC_WAIT       : 32514 }
   if !IDC {
      DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS, "UInt", 0, "UInt", 0, "UInt", 0)
      OnExit(exitFunc, 0), setOnExit := false
   }
   else {
      hCursor := (IDC + 0) ? IDC : DllCall("LoadCursor", "Ptr", 0, "UInt", SysCursors[IDC], "Ptr")
      for k, v in SysCursors  {
         hCopy := DllCall("CopyImage", "Ptr", hCursor, "UInt", IMAGE_CURSOR, "Int", 0, "Int", 0, "UInt", 0, "Ptr")
         DllCall("SetSystemCursor", "Ptr", hCopy, "UInt", v)
      }
      if !setOnExit
         OnExit(exitFunc), setOnExit := true
   }
}
jly
Posts: 89
Joined: 30 Sep 2020, 06:06

Re: How to change the system cursor??

08 May 2021, 09:47

teadrinker wrote:
08 May 2021, 06:10
Anyway dll calls are incorrect. Should be like this:

Code: Select all

$F1:: ReplaceSystemCursors((t := !t) ? "IDC_ARROW" : "")

ReplaceSystemCursors(IDC = "") ; IDC must be a cursor name like "IDC_CROSS" or cursor handle
{
   static IMAGE_CURSOR := 2, SPI_SETCURSORS := 0x57
        , exitFunc := Func("ReplaceSystemCursors").Bind("")
        , setOnExit := false
        , SysCursors := { IDC_APPSTARTING: 32650
                        , IDC_ARROW      : 32512
                        , IDC_CROSS      : 32515
                        , IDC_HAND       : 32649
                        , IDC_HELP       : 32651
                        , IDC_IBEAM      : 32513
                        , IDC_NO         : 32648
                        , IDC_SIZEALL    : 32646
                        , IDC_SIZENESW   : 32643
                        , IDC_SIZENWSE   : 32642
                        , IDC_SIZEWE     : 32644
                        , IDC_SIZENS     : 32645 
                        , IDC_UPARROW    : 32516
                        , IDC_WAIT       : 32514 }
   if !IDC {
      DllCall("SystemParametersInfo", "UInt", SPI_SETCURSORS, "UInt", 0, "UInt", 0, "UInt", 0)
      OnExit(exitFunc, 0), setOnExit := false
   }
   else {
      hCursor := (IDC + 0) ? IDC : DllCall("LoadCursor", "Ptr", 0, "UInt", SysCursors[IDC], "Ptr")
      for k, v in SysCursors  {
         hCopy := DllCall("CopyImage", "Ptr", hCursor, "UInt", IMAGE_CURSOR, "Int", 0, "Int", 0, "UInt", 0, "Ptr")
         DllCall("SetSystemCursor", "Ptr", hCopy, "UInt", v)
      }
      if !setOnExit
         OnExit(exitFunc), setOnExit := true
   }
}

Hello, teadrinker

I carefully observed the changes in the shape of Cursor.
The sharpness of the two arrows is different.
This is what I want to consult .

Can you see the difference between the two arrows before and after pressing F1?
Or this is caused by the monitor resolution.
teadrinker
Posts: 4325
Joined: 29 Mar 2015, 09:41
Contact:

Re: How to change the system cursor??

08 May 2021, 10:28

Nope, for me there is no difference:
 
 Image Image
jly
Posts: 89
Joined: 30 Sep 2020, 06:06

Re: How to change the system cursor??

08 May 2021, 10:49

teadrinker wrote:
08 May 2021, 10:28
Nope, for me there is no difference:
 
 Image Image
Ok thanks for your help!

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Exies, Google [Bot], JoeWinograd, scriptor2016 and 96 guests