13

I've written the code below to affect (what I think) are the only reg keys responsible for the size of the cursor and pointer in Windows 10.

Here's the code I have so far (Some additional comments within):

$RegConnect             = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"CurrentUser", "$env:COMPUTERNAME")
$RegCursorsAccess       = $RegConnect.OpenSubKey("Software\Microsoft\Accessibility", $true)
$RegCursorsControlPanel = $RegConnect.OpenSubKey("Control Panel\Cursors", $true)

# In the code below I'm trying to change the size of the cursor.

$RegCursorsControlPanel.SetValue("CursorBaseSize", 48)
$RegCursorsAccess.SetValue("CursorSize", 3)

$RegCursorsAccess.Close()
$RegConnect.Close()

# This section is where I thought it would update the cursor size.

# Here is where it lists stuff relating to setting and updating any settings changed.
# https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfoa
    # SPI_SETCURSORS
    # 0x0057
    # Reloads the system cursors. Set the uiParam parameter to zero and the pvParam parameter to NULL.

$CSharpSig = @'
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
public static extern bool SystemParametersInfo(
                  uint uiAction,
                  uint uiParam,
                  uint pvParam,
                  uint fWinIni);
'@
$CursorRefresh = Add-Type -MemberDefinition $CSharpSig -Name WinAPICall -Namespace SystemParamInfo -PassThru
$CursorRefresh::SystemParametersInfo(0x0057,0,$null,0)

It will change the correct values in the registry.

So if I run this PowerShell code the mouse size in the ease of access setting is at the correct value.

cursor and pointer size setting

But the cursor doesn't update.

How is it possible to force the update without logging out and back in or restarting the machine.


Here are some related MS links:

WM_SETTINGCHANGE message

SystemParametersInfoA function


EDIT - Some additional info

If I run Process Monitor from Sysinternals and dig deep in there I can see this under the stack summary.

This may lead someone more knowledgeable than me to find how to update the mouse size.

The HKCU\Control Panel\Cursors\(Default) section SettingsHandlers_nt.dll

Sysinternals Process Monitor

And this also for the accessibility section. Windows.UI.Accessibility.dll

Windows.UI.Accessibility.dll

Here are the settings I used in Process Monitors filter to narrow down the items.

Settings used as the filter

Ste
  • 1,729
  • 1
  • 17
  • 27

2 Answers2

8

So after a bit of hacking about SystemSettings.exe with cheat engine I found how MS sets the cursor size. It ends up still using SystemParametersInfo but with some undocumented arguments. Try the following :)

SystemParametersInfo(0x2029, 0, 16, 0x01);

to set a cursor size of 16. yup you can go below their minimum of 32, all the way down to 1 :)

HaPpY
  • 176
  • 3
  • 4
  • Thanks very much this works. Do you know why the UI doesn't update in this image? It only updates after a restart. https://i.imgur.com/0wJI8Ww.png – Ste Oct 25 '21 at 11:47
  • that tool sets multiple registry entries and reads from Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Accessibility\CursorSize which uses 1-15 size format. while SystemParametersInfo with 0x2029 is just Computer\HKEY_CURRENT_USER\Control Panel\Cursors\CursorBaseSize – HaPpY Oct 28 '21 at 03:39
  • Thanks, Is there a way to check which ones are changed when that slider is moved? – Ste Oct 28 '21 at 11:05
  • @Ste just handle WM_SETTINGCHANGE in your app and re-read registry values. – DJm00n Jun 30 '23 at 15:27
  • Thanks @DJm00n but if you mean update the cursor then that's solved. Or do you mean updating the window UI size? – Ste Jun 30 '23 at 19:12
  • @Ste I meant that you can handle it to have notification when cursor settings was changed in Windows. after this you can recreate your cursors with proper size. – DJm00n Jun 30 '23 at 20:27
  • I see, feel free to add an answer. Cheers. – Ste Jun 30 '23 at 21:21
2

But the cursor doesn't update.

After registry value changed, it requires trigger to apply these update.

It can be done using SystemParametersInfo function with SPIF_UPDATEINIFILE and SPIF_SENDCHANGE to writes the new system-wide parameter setting to the user profile and broadcasts the WM_SETTINGCHANGE message after updating the user profile.

SystemParametersInfo(SPI_SETCURSORS, 0, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

The following is a PowerShell command example:

$RegConnect = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"CurrentUser","$env:COMPUTERNAME")


$RegCursors = $RegConnect.OpenSubKey("Control Panel\Cursors",$true)


$RegCursors.SetValue("","Windows Black")
$RegCursors.SetValue("CursorBaseSize",0x40)

$RegCursors.SetValue("AppStarting","%SystemRoot%\cursors\wait_r.cur")

$RegCursors.SetValue("Arrow","%SystemRoot%\cursors\arrow_rl.cur")

$RegCursors.SetValue("Crosshair","%SystemRoot%\cursors\cross_r.cur")

$RegCursors.SetValue("Hand","")

$RegCursors.SetValue("Help","%SystemRoot%\cursors\help_r.cur")

$RegCursors.SetValue("IBeam","%SystemRoot%\cursors\beam_r.cur")

$RegCursors.SetValue("No","%SystemRoot%\cursors\no_r.cur")

$RegCursors.SetValue("NWPen","%SystemRoot%\cursors\pen_r.cur")

$RegCursors.SetValue("SizeAll","%SystemRoot%\cursors\move_r.cur")

$RegCursors.SetValue("SizeNESW","%SystemRoot%\cursors\size1_r.cur")

$RegCursors.SetValue("SizeNS","%SystemRoot%\cursors\size4_r.cur")

$RegCursors.SetValue("SizeNWSE","%SystemRoot%\cursors\size2_r.cur")

$RegCursors.SetValue("SizeWE","%SystemRoot%\cursors\size3_r.cur")

$RegCursors.SetValue("UpArrow","%SystemRoot%\cursors\up_r.cur")

$RegCursors.SetValue("Wait","%SystemRoot%\cursors\busy_r.cur")

$RegCursors.Close()

$RegConnect.Close()


function Update-UserPreferencesMask {
$Signature = @"
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, uint pvParam, uint fWinIni);

const int SPI_SETCURSORS = 0x0057;
const int SPIF_UPDATEINIFILE = 0x01;
const int SPIF_SENDCHANGE = 0x02;

public static void UpdateUserPreferencesMask() {
    SystemParametersInfo(SPI_SETCURSORS, 0, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
"@
    Add-Type -MemberDefinition $Signature -Name UserPreferencesMaskSPI -Namespace User32
    [User32.UserPreferencesMaskSPI]::UpdateUserPreferencesMask()
}
Update-UserPreferencesMask

But unfortunately, the cursor size update doesn't work in this way.

A workaround is using arrow_rl.cur (large image) instead of arrow_r.cur.

Refer to Use PowerShell to Change the Mouse Pointer Scheme, Programmatically change custom mouse cursor in windows.

Ste
  • 1,729
  • 1
  • 17
  • 27
Rita Han
  • 9,574
  • 1
  • 11
  • 24
  • Thanks. This is why I was trying to change the registry item of both values which are interlinked. The `CursorSize` and `CusorBaseSize`. Unfortunately, this workaround isn't what I was after. I wanted to control it like how the access setting does, only to keep the existing style. But this part is beyond the scope of the question. If I can set the size then the other won't be as difficult. – Ste Feb 07 '20 at 10:29
  • @Ste If edit size and color from system setting is ok for you, you can consider [UI Automation](https://learn.microsoft.com/en-us/windows/win32/winauto/entry-uiauto-win32). – Rita Han Feb 10 '20 at 00:29
  • Hi, I'm not sure. If you're not aware when you set a certain style as your cursor and you change the size, the style is lost. I can change the style but I wanted to chage the size while keeping the existing scheme. My end goal here is to export a `.reg` file of the existing scheme, change the cursor size (while not restarting) and then reimport the `.reg` file back in again. This is the only workaround I can see. But this thread is primarily about setting the size. Have you an example of how this UI automation could work in regards my issue? – Ste Feb 10 '20 at 12:12
  • have you ever found a solution to this issue? This AHK script also uses SPI_SETCURSORS (0x57) and it works, but I can't figure out how to use it to change the size of the cursor - https://autohotkey.com/board/topic/32608-changing-the-system-cursor/ – shadowz1337 Aug 06 '21 at 00:42