Reputation: 2293
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.
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:
SystemParametersInfoA function
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
And this also for the accessibility section. Windows.UI.Accessibility.dll
Here are the settings I used in Process Monitors filter to narrow down the items.
Upvotes: 14
Views: 8897
Reputation: 306
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 :)
Upvotes: 10
Reputation: 9700
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.
Upvotes: 2