Disable animation effects for windows with C#

2019-07-19 06:57发布

I'm trying to disable the "fading" animation in windows which happens whenever you open or maximize/minimize a window.

Of course it can be done manually by unticking the checkbox of animate windows when minimizing and maximizing

I'm trying to do this through the SystemParametersInfo This is my call:

    [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 value is always True , so I know the function was successfully called.

But I can't see any results...Windows still keep animating any window I resize.

I compile this as AnyCPU, running as adminstrator on Windows 10.

for @cody gray this is the code (added the ref keyword to the ai paramater and converted the Marshal.Sizeof(ai) to `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);
     }

One last question-if i would like to get back to the original state-which means i want to activate the aniamtions again,what parameter should be changed in order to do this?

1条回答
Explosion°爆炸
2楼-- · 2019-07-19 07:18

You are not setting the right option when you call SystemParametersInfo. The one that controls the minimize/maximize animation effect (labeled in the UI as "Animate windows when minimizing and maximizing") is SPI_SETANIMATION.

Using it is a bit more complicated, because the pvParam parameter must point to an ANIMATIONINFO structure. It is rather pointless, because the struct only has one meaningful member, but that's the way the API was designed. Presumably, the intent years ago was for this to be a toggle for all of the shell animation effects, but for whatever reason, that didn't end up happening, and separate SPI_* values were used for each of them. You unfortunately picked the wrong one. It is a long list.

Sample code in 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);
}

Note that this is a global setting, affecting all applications. It is exceedingly rare that an application would ever need to toggle this switch, unless you were making a desktop customization utility. As such, you will require administrative privileges to change this setting.


There is also the DWMWA_TRANSITIONS_FORCEDISABLED flag that you can use with the DwmSetWindowAttribute function to disable transitions when a window is hidden or shown.

The advantage of this is that it is a local solution—you can change the setting only for a single window. But it won't do anything if you are not using DWM (on older versions of Windows), and the minimize/maximize transitions may still be visible. I haven't comprehensively tested the interaction between these two options.

Hans Passant linked you to one of his answers that contains an embedded example of how to call DwmSetWindowAttribute from C#. Here are the relevant bits:

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));
}
查看更多
登录 后发表回答