Proper way to call AnimateWindow with a .NET WinForms Form?
-
14-03-2021 - |
Question
i'm trying to call AnimateWindow
to animate the show and hide of a WinForms window.
Here's a copy of the win32 translation:
private static class NativeMethods
{
public const int AW_ACTIVATE = 0x20000;
public const int AW_HIDE = 0x10000;
public const int AW_BLEND = 0x80000;
public const int AW_CENTER = 0x00000010;
public const int AW_SLIDE = 0X40000;
public const int AW_HOR_POSITIVE = 0x1;
public const int AW_HOR_NEGATIVE = 0X2;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int AnimateWindow(IntPtr hwand, int dwTime, int dwFlags);
}
But the problem is how to fit a call to AnimateWindow
into the) WinForms scheme. One person suggests OnLoad:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
AnimateWindow(this.Handle, 200, AW_ACTIVATE | AW_HOR_NEGATIVE | AW_SLIDE);
}
and OnClosing:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (e.Cancel == false)
{
AnimateWindow(this.Handle, 200, AW_HIDE | AW_HOR_POSITIVE | AW_SLIDE);
}
}
Except that it doesn't work.
- the form doesn't use any animation while appearing
- during hide the form animates its horizontal slide off the screen, then reappears, before hiding the normal way
What is the correct way to mix AnimateWindow
with WinForms?
See also
- .NET AnimateWindow: this guy asked the same question. But since it was trying to achieve something else, people solved his problem rather than answering his question.
- C# WinForms AnimateWindow issue: This guy was interested in using
AnimateWindow
with child controls, rather than a top-level window.
Bonus Chatter
i was perusing through the Form -> Show -> Visible -> SetVisibleCore
, when i discovered this bug:
protected virtual void SetVisibleCore(bool value)
{
try
{
HandleCollector.SuspendCollect();
//...snip...
}
finally
{
HandleCollector.ResumeCollect();
}
}
Nice to know that everyone can introduce these subtle errors.
No correct solution
OTHER TIPS
I think AnimateWindow
has it's limitations to work properly. For example, it doesn't play well with Aero, so to animate a sliding form, you would need to set the BorderStyle
to None. Also, make sure the StartPosition
is set to Manual.
Simple example:
public partial class Form1 : Form {
public const int AW_ACTIVATE = 0x20000;
public const int AW_HIDE = 0x10000;
public const int AW_BLEND = 0x80000;
public const int AW_CENTER = 0x00000010;
public const int AW_SLIDE = 0X40000;
public const int AW_HOR_POSITIVE = 0x1;
public const int AW_HOR_NEGATIVE = 0X2;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int AnimateWindow(IntPtr hwand, int dwTime, int dwFlags);
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
Form toastForm = new Form();
toastForm.ShowInTaskbar = false;
toastForm.StartPosition = FormStartPosition.Manual;
toastForm.FormBorderStyle = FormBorderStyle.None;
toastForm.Size = new Size(256, 64);
toastForm.Location = new Point(Screen.PrimaryScreen.WorkingArea.Right - toastForm.Width,
Screen.PrimaryScreen.WorkingArea.Bottom - toastForm.Height);
Button closeButton = new Button();
closeButton.Text = "Close";
toastForm.Controls.Add(closeButton);
closeButton.Click += delegate { toastForm.Close(); };
AnimateWindow(toastForm.Handle, 200, AW_ACTIVATE | AW_HOR_NEGATIVE | AW_SLIDE);
toastForm.Show();
}
}
I'm not sure what your AnimateWindow
call does, but when you need to change underlying native 'stuff' to do with windows forms, I've always used the CreateParams() override. You may
find a similar function for what you are trying to achieve.
Here's an example of a transparent tool window, that doesn't activate when it is shown.
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim baseParams As Windows.Forms.CreateParams = MyBase.CreateParams
baseParams.ExStyle = baseParams.ExStyle Or NativeMethods.ExtendedWindowsStyles.WS_EX_LAYERED Or NativeMethods.ExtendedWindowsStyles.WS_EX_TRANSPARENT Or NativeMethods.ExtendedWindowsStyles.WS_EX_NOACTIVATE Or NativeMethods.ExtendedWindowsStyles.WS_EX_TOOLWINDOW
Return baseParams
End Get
End Property