2

I would like to know how to suppress the animations when calling the HWnd ShowWindow() method. Here is my code:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);

public enum ShowWindowCommands
{
    HIDE = 0,
    SHOWNORMAL = 1,
    SHOWMINIMIZED = 2,
    MAXIMIZE = 3,
    SHOWNOACTIVATE = 4,
    SHOW = 5,
    MINIMIZE = 6,
    SHOWMINNOACTIVE = 7,
    SHOWNA = 8,
    RESTORE = 9,
    SHOWDEFAULT = 10,
    FORCEMINIMIZE = 11
}

public static void MinimizeWindow(IntPtr hWnd)
{
    ShowWindow(hWnd, ShowWindowCommands.MINIMIZE);
}

The problem is, the animation executes, and the method does not return until the animation is finished.

I tried using the DwmSetWindowAttribute() method:

[DllImport("dwmapi.dll", PreserveSig = true)]
static extern int DwmSetWindowAttribute(IntPtr hWnd, uint attr, ref int attrValue, int size);

const uint DWM_TransitionsForceDisabled = 3;

public static void SetEnabled(IntPtr hWnd, bool enabled)
{
    int attrVal = enabled ? 0 : 1;
    DwmSetWindowAttribute(hWnd, DWM_TransitionsForceDisabled, ref attrVal, 4);
}

But the animations were not suppressed. My operating system is Windows 7, 32-bit.

Mr Anderson
  • 2,200
  • 13
  • 23
  • Check the return value of `DwmSetWindowAttribute` to see if it's failing and if so why. – Jonathan Potter Jun 07 '16 at 06:02
  • @Jonathan Potter The return value is zero, i.e. operation successful – Mr Anderson Jun 07 '16 at 06:27
  • See the answer to http://stackoverflow.com/questions/6160118/disable-aero-peek-in-wpf-application, it looks like you're passing the data pointer incorrectly. – Jonathan Potter Jun 07 '16 at 06:30
  • When I change the method signature to use IntPtr, it returns code 0x800703e6 (invalid access to memory location). The signature I was using should be ok, as it was the one used in the link in my question. – Mr Anderson Jun 07 '16 at 06:39
  • 1
    The posted snippets are correct. Look for a simple mistake like calling SetEnabled() too late or inverting the meaning of its *enabled* argument or using the wrong window handle. – Hans Passant Jun 07 '16 at 07:45

2 Answers2

1

https://devblogs.microsoft.com/oldnewthing/20121003-00/?p=6423


BOOL ani = TRUE;
DwmSetWindowAttribute(m_top, DWMWA_TRANSITIONS_FORCEDISABLED, &ani, sizeof(ani));

Hunker
  • 97
  • 9
-1

Not the best option, but you can try calling SystemParametersInfo() specifying SPI_GETANIMATION to get the current setting for window animations, and if enabled then use SPI_SETANIMATION to disable them before showing the window, then restore the previous setting. For example:

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

[DllImport("User32.dll", SetLastError=true)]
static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref ANIMATIONINFO pvParam, uint fWinIni);

const uint SPI_GETANIMATION = 72;
const uint SPI_SETANIMATION = 73;

public static void MinimizeWindow(IntPtr hWnd)
{
    ANIMATIONINFO anim;
    anim.cbSize = Marshal.SizeOf(anim);
    anim.iMinAnimate = 0;

    SystemParametersInfo(SPI_GETANIMATION, Marshal.SizeOf(anim), anim, 0);

    if (anim.iMinAnimate != 0)
    {
        anim.iMinAnimate = 0;
        SystemParametersInfo(SPI_SETANIMATION, Marshal.SizeOf(anim), anim, 0);

        ShowWindow(hWnd, ShowWindowCommands.MINIMIZE);

        anim.iMinAnimate = 1;
        SystemParametersInfo(SPI_SETANIMATION, Marshal.SizeOf(anim), anim, 0);
    }
    else
        ShowWindow(hWnd, ShowWindowCommands.MINIMIZE);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 3
    Generally referred to on the Old New Thing blog as "using a global setting to fix a local problem" and usually [frowned upon](https://blogs.msdn.microsoft.com/oldnewthing/20081211-00/?p=19873) – Damien_The_Unbeliever Jun 07 '16 at 06:41
  • The strange thing is, even when I use this global solution the animation still shows :( – Mr Anderson Jun 07 '16 at 06:43
  • @Damien_The_Unbeliever: granted, but I don't know any other way to turn off window animations locally. – Remy Lebeau Jun 07 '16 at 17:17
  • @RemyLebeau - well, the OP seems to have already taken themselves down such a route already. They're trying to make use of functions with a local effect. Why it's not working is unclear. – Damien_The_Unbeliever Jun 07 '16 at 17:23
  • @Damien_The_Unbeliever which is why I dismissed that as a possible solution, and offered an alternative (albeit a global one, but only for a few milliseconds at a time). – Remy Lebeau Jun 07 '16 at 17:32
  • `SPI_GETANIMATION` and `SPI_SETANIMATION` use an `ANIMATIONINFO` structure, not a simple `BOOL`. – Jonathan Potter Jun 07 '16 at 18:50
  • @JonathanPotterL so what? You can retrieve the current [`ANIMATIONINFO`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724197.aspx) with `SPI_GETANIMATION` and then restore the same `ANIMATIONINFO` with `SPI_SETANIMATION`. It only has 2 fields, `UINT cbSize` and `int iMinAnimate`, where `iMinAnimate` is either zero or non-zero. This is not an uncommon solution to use when disabling minimize/restore animations, for lack of another API that accomplishes the same thing. – Remy Lebeau Jun 07 '16 at 18:59
  • 2
    @RemyLebeau - I am not opposed to this answer, but it is not working for me either. The only solution that has worked for me is this one: http://www.addictivetips.com/windows-tips/disable-the-maximize-minimize-windows-animation-in-windows-7/ but I need it done programmatically, obviously. I'm beginning to think it could be an issue with my environment (VirtualBox vm) – Mr Anderson Jun 07 '16 at 19:22
  • @MrAnderson: that setting is exactly what `SPI_SETANIMATION` is supposed to be updating. Makes me wonder if your app is not running with sufficient rights to alter system settings? That would definitely be an issue if `SPI_SETANIMATION` requires that. – Remy Lebeau Jun 07 '16 at 19:42
  • @RemyLebeau so what? so your answer probably led the OP to believe he just needed a `BOOL`, rather than a valid `ANIMATIONINFO` structure, that's what. – Jonathan Potter Jun 08 '16 at 00:00
  • 1
    @JonathanPotter Actually I was familiar with the signature of SystemParametersInfo even before he edited the answer. I just installed a service pack for my OS and the SystemParametersInfo method is now working, however the DwmSetWindowAttribute still does not work. – Mr Anderson Jun 08 '16 at 02:33
  • To get `SystemParametersInfo` to work with `SPI_GETANIMATION` you should set uiParam to the structure size instead of 0 `SystemParametersInfo(SPI_GETANIMATION, Marshal.SizeOf(anim), anim, 0);` – Ahmed Osama Nov 22 '20 at 18:19
  • 1
    @AhmedOsama apparently the same for `SPI_SETANIMATION`, too. – Remy Lebeau Nov 22 '20 at 19:20