Using AnimateWindow() at Form_Load

1

I have a borderless form and I use the AnimateWindow() method to create animations for opening, closing, etc my Form. I use this code:

[Flags]
enum AnimateWindowFlags
{
    AW_HOR_POSITIVE = 0x0000000
    AW_HOR_NEGATIVE = 0x00000002,
    AW_VER_POSITIVE = 0x00000004,
    AW_VER_NEGATIVE = 0x00000008,
    AW_CENTER = 0x00000010,
    AW_HIDE = 0x00010000,
    AW_ACTIVATE = 0x00020000,
    AW_SLIDE = 0x00040000,
    AW_BLEND = 0x00080000
}

[DllImport("user32.dll")]
static  extern bool AnimateWindow(IntPtr hWnd, int time, AnimateWindowFlags flags);

When it comes to closing the form, this code seems to work:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    AnimateWindow(this.Handle, 100, AnimateWindowFlags.AW_BLEND | AnimateWindowFlags.AW_HIDE);
}

However, when opening the form with this code:

private void Form1_Load(object sender, EventArgs e)
{
    AnimateWindow(this.Handle, 100, AnimateWindowFlags.AW_BLEND);
}

Nothing seems to happen. After doing some guesses and tests I figured that using the AnimateWindow() method to make the form fade out works, but using it to make the form fade in doesn't do anything (regardless of the time parameter).

Any ideas?

c#
winforms
borderless
animatewindow
asked on Stack Overflow Jul 22, 2015 by OC_

1 Answer

2

This is pretty difficult to do correctly, there is an enormous amount of code involved that is very tricky to reason through. The Visible property, set by the Application class for the startup form and the Show() method when you create your own is a very big deal in Winforms. The native window creation is lazy in typical .NET fashion, lots and lots of stuff happens when the ball gets rolling.

The AnimateWindow() call must be injected in between the time the Show() method is called and Winforms gets a chance to pinvoke ShowWindow(). It is the latter call that ruins the animation effect when you try it in OnLoad(), the event fires too late.

You can try this code, paste it into your Form class:

    protected override void SetVisibleCore(bool value) {
        if (!this.IsHandleCreated) {
            NativeMethods.AnimateWindow(this.Handle, 100, AnimateWindowFlags.AW_BLEND);
        }
        base.SetVisibleCore(value);
    }

    protected override void OnShown(EventArgs e) {
        this.BringToFront();
        base.OnShown(e);
    }

But I cannot promise it will work in all possible cases and have not tested it extensively. Having to call BringToFront() was already an unpleasant hack. Don't try it on an MDI child form, not likely to come to a good end.

answered on Stack Overflow Jul 22, 2015 by Hans Passant • edited Jul 23, 2015 by Hans Passant

User contributions licensed under CC BY-SA 3.0