SystemParametersInfo和SPI_SETCURSORS失败,没有错误

时间:2014-07-11 15:31:54

标签: c# winapi pinvoke

这个真的让我疯了。我进行了搜索和搜索,觉得我是唯一有这个问题的人。所以我希望能在这里进行一些理智的检查。

首先,上下文 - 我正在为专用游戏机创建一个简单的替换shell。 shell的一部分是隐藏光标。我已经找到了很多示例,通过编辑注册表然后告诉Windows刷新游标来显示如何执行此操作。

注册表代码没有问题,工作正常。但是,后续对SystemParametersInfo的调用每次都会失败。更糟糕的是,对Marshal.GetLastWin32Error()的跟进调用返回0。

最初,我在Windows 8.1计算机上尝试了这些代码,并将其归结为某种Windows 8问题。但是,该代码也无法在Windows 7(x64 SP1)上运行。

以下示例代码说明了我遇到的问题:

class Program
{
    //a
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);

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

    //c
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref uint pvParam, uint fWinIni);

    //d
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SystemParametersInfo(uint uiAction, uint uiParam, string pvParam, uint fWinIni);

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

    static uint _pvParam = 0;

    static void Main(string[] args)
    {
        //a
        var a = SystemParametersInfo(SPI_SETCURSORS, 0, IntPtr.Zero, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
        var ax = Marshal.GetLastWin32Error();

        //b
        var b = SystemParametersInfo(SPI_SETCURSORS, 0, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
        var bx = Marshal.GetLastWin32Error();

        //c
        var c = SystemParametersInfo(SPI_SETCURSORS, 0, ref _pvParam, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
        var cx = Marshal.GetLastWin32Error();

        //d
        var d = SystemParametersInfo(SPI_SETCURSORS, 0, null, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
        var dx = Marshal.GetLastWin32Error();

        Console.WriteLine("a: {0}\tax: {1}", a, ax);
        Console.WriteLine("b: {0}\tbx: {1}", b, bx);
        Console.WriteLine("c: {0}\tcx: {1}", c, cx);
        Console.WriteLine("d: {0}\tdx: {1}", d, dx);

    }
}

我的结果总是:

a: False        ax: 0
b: False        bx: 0
c: False        cx: 0
d: False        dx: 0

如果有人可以运行此代码告诉我它是否适合他们,我会很高兴。或者更好地指出我缺少的明显问题。 :)

编辑:尝试了这种方法签名,但它不起作用:

[DllImport("user32.dll", SetLastError = true)]
static extern bool SystemParametersInfo(int uiAction, int uiParam, IntPtr pvParam, int fWinIni);

编辑2:另外值得注意的是:您可以在不传递SPIF_UPDATEINIFILE的情况下调用该方法,它将返回“True”。但是,它不会成功重新加载游标。

这基本上就是我要做的事:http://www.daveamenta.com/2013-08/programmatically-update-the-mouse-cursors-with-powershell/

2 个答案:

答案 0 :(得分:0)

导入不应该如此:

[DllImport("user32.dll", SetLastError = true)]
static extern bool SystemParametersInfo(int uiAction, int uiParam, IntPtr pvParam, int fWinIni);

答案 1 :(得分:0)

我在C ++程序中也得到了一个repro。不寻常的错误。使用SPIF_UPDATEINIFILE让你很生气。只要删除那个标志就可以了。

请注意那些超载btw,您需要删除 uint 版本。