使用C#禁用Windows的动画效果

时间:2016-07-15 12:14:54

标签: c# .net windows winapi animation

我试图禁用"褪色"窗口中的动画,无论何时打开或最大化/最小化窗口都会发生。

当然可以通过在最小化和最大化时取消选中动画窗口的复选框来手动完成

我试图通过SystemParametersInfo来做到这一点 这是我的电话:

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

    private static UInt32 SPIF_SENDCHANGE = 0x02;
    private static UInt32 SPI_SETUIEFFECTS = 0x103F;
    public static void Main()
    {
      bool res=  SystemParametersInfo(SPI_SETUIEFFECTS, 0, false, SPIF_SENDCHANGE);
    }

result值始终为 True ,因此我知道该函数已成功调用。

但是我无法看到任何结果...... Windows仍会保持动画调整我调整大小的窗口。

我将其编译为AnyCPU,在Windows 10上作为管理员运行。

对于@cody grey这是代码(将ref关键字添加到ai参数并将Marshal.Sizeof(ai)转换为`uint)。

     [StructLayout(LayoutKind.Sequential)]
     public struct ANIMATIONINFO
     {
         public uint cbSize;
         public int iMinAnimate;
     };

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

     public static uint SPIF_SENDCHANGE = 0x02;
     public static uint SPI_SETANIMATION = 0x0049;

     public static void Main()
     {
         ANIMATIONINFO ai=new ANIMATIONINFO();
         ai.cbSize = (uint)Marshal.SizeOf(ai);
         ai.iMinAnimate = 0;   // turn all animation off
         SystemParametersInfo(SPI_SETANIMATION, 0,  ref ai, SPIF_SENDCHANGE);
     }

最后一个问题 - 如果我想回到原始状态 - 这意味着我想再次激活aniamtions,应该更改哪个参数才能执行此操作?

1 个答案:

答案 0 :(得分:2)

致电SystemParametersInfo时,您没有设置正确的选项。控制最小化/最大化动画效果的那个(在UI中标记为“最小化和最大化时动画窗口”)是SPI_SETANIMATION

使用它有点复杂,因为pvParam参数必须指向ANIMATIONINFO结构。这是毫无意义的,因为struct只有一个有意义的成员,但这就是API的设计方式。据推测,几年前的目的是为了实现所有 shell动画效果的切换,但无论出于何种原因,最终都没有发生,并且单独的SPI_*值是用于他们每个人。你不幸的是选错了。它是a long list

C#中的示例代码:

[StructLayout(LayoutKind.Sequential)]
public struct ANIMATIONINFO
{
    public uint cbSize;
    public int  iMinAnimate;
};

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

public static uint SPIF_SENDCHANGE  = 0x02;
public static uint SPI_SETANIMATION = 0x0049;

public static void Main()
{
    ANIMATIONINFO ai;
    ai.cbSize      = Marshal.SizeOf(ai);
    ai.iMinAnimate = 0;   // turn all animation off
    SystemParametersInfo(SPI_SETANIMATION, 0, ai, SPIF_SENDCHANGE);
}

请注意,这是 全局设置,会影响所有应用程序。除非您正在制作桌面自定义实用程序,否则应用程序需要切换此开关的情况极为罕见。因此,您将需要管理员权限才能更改此设置。

还有 DWMWA_TRANSITIONS_FORCEDISABLED标志,您可以使用DwmSetWindowAttribute function在隐藏或显示窗口时禁用转换。

这样做的好处是它是一个本地解决方案 - 您只能为单个窗口更改设置。但是,如果您不使用DWM(在旧版本的Windows上),它将不会执行任何操作,并且最小化/最大化转换可能仍然可见。我没有全面测试这两种选项之间的相互作用。

Hans Passant将您链接到one of his answers,其中包含有关如何从C#调用DwmSetWindowAttribute的嵌入式示例。以下是相关内容:

const int DWMWA_TRANSITIONS_FORCEDISABLED = 3;

[DllImport("dwmapi", PreserveSig = true))]
static extern int DwmSetWindowAttribute(IntPtr hWnd, int attr, ref int value, int attrLen);
// in the form's constructor:
// (Note: in addition to checking the OS version for DWM support, you should also check
// that DWM composition is enabled---or at least gracefully handle the function's
// failure when it is not. Instead of S_OK, it will return DWM_E_COMPOSITIONDISABLED.)
if (Environment.OSVersion.Version.Major >= 6)
{
    int value = 1;  // TRUE to disable
    DwmSetWindowAttribute(this.Handle,
                          DWMWA_TRANSITIONS_FORCEDISABLED,
                          ref value,
                          Marshal.SizeOf(value));
}