2

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?

OC_
  • 446
  • 6
  • 19
  • 1
    It probably won't work correctly in the Load event since the form may not yet have a handle at that point. Try it in the Form_Shown event and see if it works there. – Chris Dunaway Jul 22 '15 at 16:33
  • Hm, gave this a try, didn't seem to do anything. However, I tried using AnimateWindow() to hide (to fade out) my form and it worked. I was thinking that I use this method in a wrong way, but according to this http://www.dreamincode.net/forums/topic/109668-animating-a-windows-form/ it should work... – OC_ Jul 22 '15 at 17:24

1 Answers1

4

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • +1 for effort, but it doesn't work in the project that I'm working on. What's strange is when I made an new project (just an empty borderless form) both mine and your way worked! Then I added some components like a couple of buttons and a tab control (since my program actually has some of these) and it still worked, so there's probably something with my project. I'll take a look and will let you know. – OC_ Jul 23 '15 at 08:06
  • Ok, I just found who is guilty of all this: `this.MaximizedBounds = Screen.FromControl(this).WorkingArea;`. I use this so that the main form (which is borderless) fits exactly the screen (so that it doesn't cover the taskbar and to prevent some parts to go outside the screen). Simply removing seems to solve the problem... – OC_ Jul 23 '15 at 10:36
  • Sure, it is the kind of statement that causes the trouble I've warned about. Any code that depends on the Size or Location of a form, or implicitly uses the Handle property like Screen.FromControl() does, should be moved into the Load event handler. Something you can see with the debugger by setting a breakpoint on the AnimateWindow() call, you never want to see the form's constructor call in the Call Stack trace. – Hans Passant Jul 23 '15 at 11:00