C# - AnimateWindow (Win32API) を試してみた

タスクトレイから呼ぶフォーム用に、
「ひょこっ」とした感じでウィンドウを表示したかった。

# 結果

スライドアニメーション(`AW_SLIDE`)はイマイチ。
・カクカク感がある
・タイトルバーが先に表示されてしまう（↓方向だけは視覚的にセーフ？）

フェードアニメーション(`AW_BLEND`)は、まぁよさげ。
・ただし、時間設定を長め（1000msとか）にすると複数回フェードするような挙動をした。謎。


# サンプルコード(簡素版)

```cs

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public class AnimateWindowTest: Form
{
    Button btn;

    class NativeMethods
    {
        [Flags]
        public enum AnimateWindowFlags {
            AW_NONE = 0,
            AW_HOR_POSITIVE = 0x00000001,
            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")]
        public static extern bool AnimateWindow(IntPtr hWnd, UInt32 dwTimeMSec, AnimateWindowFlags dwFlags);
    }

    AnimateWindowTest()
    {
        btn = new Button();
        btn.Text = "New Window";
        btn.Click += Btn_Click;
        Controls.Add(btn);

        ClientSize = new Size(200,100);
    }

    void Btn_Click(object sender, EventArgs e)
    {
        Form f = new Form();
        f.Controls.Add(new Button(){Text="button",Dock=DockStyle.Bottom});
        NativeMethods.AnimateWindow(
            f.Handle,
            500, // delay tiem in [ms]
            NativeMethods.AnimateWindowFlags.AW_ACTIVATE |
            NativeMethods.AnimateWindowFlags.AW_SLIDE |
            NativeMethods.AnimateWindowFlags.AW_VER_NEGATIVE
        );
        f.Show();
    }

    [STAThread]
    static void Main(string[] args)
    {
        Application.Run(new AnimateWindowTest());
    }
}
```


# サンプルコード(子Formに処理を持たせる版)

```cs

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public class AnimateWindowTest: Form
{
    Button btn;

    AnimateWindowTest()
    {
        btn = new Button();
        btn.Text = "New Window";
        btn.Click += Btn_Click;
        Controls.Add(btn);

        ClientSize = new Size(200,100);
    }

    void Btn_Click(object sender, EventArgs e)
    {
        Form f = new AnimForm();

        f.Show();
    }

    [STAThread]
    static void Main(string[] args)
    {
        Application.Run(new AnimateWindowTest());
    }
}

public class AnimForm:Form
{
    class NativeMethods
    {
        [Flags]
        public enum AnimateWindowFlags {
            AW_NONE = 0,
            AW_HOR_POSITIVE = 0x00000001,
            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")]
        public static extern bool AnimateWindow(IntPtr hWnd, UInt32 dwTimeMSec, AnimateWindowFlags dwFlags);
        
        public const int WM_SHOWWINDOW = 0x0018;
    }

    public AnimForm()
    {
        Controls.Add(new Button(){Text="button",Dock=DockStyle.Bottom});
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == NativeMethods.WM_SHOWWINDOW) {
            //base.WndProc(ref m);
            if (m.LParam == IntPtr.Zero && m.WParam != IntPtr.Zero ) {
                // lParam == 0 : message by ShowWindow
                // mParam == 1 : being shown
                // mParam == 0 : being hidden
                NativeMethods.AnimateWindow(
                    this.Handle,
                    100, // delay tiem in [ms]
                      NativeMethods.AnimateWindowFlags.AW_ACTIVATE
                    | NativeMethods.AnimateWindowFlags.AW_BLEND //AW_SLIDE
                    // | NativeMethods.AnimateWindowFlags.AW_VER_NEGATIVE
                );
            }
            else{
                base.WndProc(ref m);
            }
        }
        else {
            base.WndProc(ref m);
        }
    }
}

```

# 参考サイト

1. http://calc33.blog57.fc2.com/blog-entry-1.html
2. http://blogs.wankuma.com/youryella/archive/2007/09/16/96512.aspx
3. [AnimateWindow API - Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-animatewindow)