6

We are basically creating a control panel applet. We need to toggle "Enhance pointer precision" in Mouse Properties.
To do so we need to call SystemParametersInfo with SPI_GETMOUSE. It has an array of 3 elements as its third parameter. I'm new to PInvoke and I've tried many signatures but so far no luck. Here is what I've tried for the signature:

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SystemParametersInfo(uint uiAction, uint uiParam, [MarshalAs(UnmanagedType.LPArray)] ref long[] vparam, SPIF fWinIni);  

static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref long[] vparam, SPIF fWinIni);

None of the above worked for me and here's the exception I'm getting:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
While searching I came up with this which is in VB.

Solution: Thanks to GWLlosa's answer and this one I came up with the solution:

[DllImport("user32.dll", EntryPoint = "SystemParametersInfo", SetLastError = true)]
public static extern bool SystemParametersInfoGet(uint action, uint param, IntPtr vparam, SPIF fWinIni);
public const UInt32 SPI_GETMOUSE = 0x0003;
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo", SetLastError = true)]
public static extern bool SystemParametersInfoSet(uint action, uint param, IntPtr vparam, SPIF fWinIni);
public const UInt32 SPI_SETMOUSE = 0x0004;
public static bool ToggleEnhancePointerPrecision(bool b)
{
    int[] mouseParams = new int[3];
    // Get the current values.
    SystemParametersInfoGet(SPI_GETMOUSE, 0, GCHandle.Alloc(mouseParams, GCHandleType.Pinned).AddrOfPinnedObject(), 0);
    // Modify the acceleration value as directed.
    mouseParams[2] = b ? 1 : 0;
    // Update the system setting.
    return SystemParametersInfoSet(SPI_SETMOUSE, 0, GCHandle.Alloc(mouseParams, GCHandleType.Pinned).AddrOfPinnedObject(), SPIF.SPIF_SENDCHANGE);
}

Also this documentation proved to be helpful.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
SepehrM
  • 1,087
  • 2
  • 20
  • 44
  • I think you should make it `int[]` instead of `ref long[]`. – Henrik Jul 14 '14 at 13:46
  • I think you would have a memory leak if you don't free the `GCHandle` instances you allocate - perhaps with some try/finally. – LOAS Jan 18 '22 at 14:14

1 Answers1

2

Have you tried:

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, IntPtr pvParam, SPIF fWinIni);

Shamelessly lifted from:

http://www.pinvoke.net/default.aspx/user32/SystemParametersInfo.html

GWLlosa
  • 23,995
  • 17
  • 79
  • 116