Use windows animations on borderless form

我的未来我决定 提交于 2019-12-03 21:36:28

It doesn't seem possible to have the animation effect on a borderless form. However, there are two possible workarounds.

  1. Set the FormBorderStyle back to Sizable just before a Minimize or Restore, and then back to none aftewards.

  2. Use the AnimateWindow function instead. The animations tend to happen where the window is currently located. The functions can be applied to any Control, not just top level windows.

Here is some sample code:

    class FormA : Form {

        private const int WM_SYSCOMMAND = 0x0112;
        private const int SC_MINIMIZE = 0xF020;
        private const int SC_RESTORE = 0xF120; 
        protected override void WndProc(ref Message m) {
            switch (m.Msg) {
                case WM_SYSCOMMAND:
                    int command = m.WParam.ToInt32();
                    if (command == SC_RESTORE) {
                        this.FormBorderStyle = FormBorderStyle.Sizable;
                        this.ControlBox = true;
                    }
                break;
            }
            base.WndProc(ref m);
        }
    }

[DllImport("user32.dll")]
static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags);

private const int AW_VER_POSITIVE = 0x00000004;
private const int AW_VER_NEGATIVE = 0x00000008;
private const int AW_SLIDE =        0x00040000;
private const int AW_HIDE = 0x00010000;


            [STAThread]
            static void Main() {
                Application.EnableVisualStyles();
                Form f = new FormA();
                f.ControlBox = false;
                f.FormBorderStyle = FormBorderStyle.None;

                bool isMinimizing = false;
                var mb = new Button { Text = "Min" };
                mb.Click += delegate {
                    isMinimizing = true;
                    f.FormBorderStyle = FormBorderStyle.Sizable;
                    f.ControlBox = true;
                    f.WindowState = FormWindowState.Minimized;
                    f.FormBorderStyle = FormBorderStyle.None;
                    isMinimizing = false;
                    //AnimateWindow(f.Handle, 300, AW_SLIDE | AW_VER_POSITIVE | AW_HIDE);

                };
                f.SizeChanged += delegate {
                    if (isMinimizing)
                        return;
                    if (f.WindowState != FormWindowState.Minimized)
                        f.FormBorderStyle = FormBorderStyle.None;
                };

                f.Controls.Add(mb);
                Application.Run(f);
        }

I know that this question has been asked over a year ago, but i had the same problem and found a very nice solution. Look at this repo at Github.
Add FormBase.cs and Native.cs to your project.

What you have to do is basically to create a Form, f.e. Main.cs and derive it from FormBase

Main.cs

public Main()
{
        InitializeComponent();

        // Redraw gripper on resize
        this.SetStyle(ControlStyles.ResizeRedraw, true);
        // Ability to minimize/restore the form with animation
        this.FormBorderStyle = FormBorderStyle.Sizable;
}

// Draw the gripper on the bottom right corner
protected override void OnPaint(PaintEventArgs e)
{
        Rectangle rc = new Rectangle(this.ClientSize.Width - cGrip, this.ClientSize.Height - cGrip, cGrip, cGrip);
        ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
        rc = new Rectangle(0, 0, this.ClientSize.Width, cCaption);
        e.Graphics.FillRectangle(Brushes.DarkBlue, rc);
        SizeGripStyle = SizeGripStyle.Hide;
}

// Override WndProc to add resize ability -> Cursor
protected override void WndProc(ref Message m)
{
        if (m.Msg == 0x84)
        {  // Trap WM_NCHITTEST
            Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
            pos = this.PointToClient(pos);
            if (pos.X >= this.ClientSize.Width - cGrip && pos.Y >= this.ClientSize.Height - cGrip)
            {
                m.Result = (IntPtr)17; // HTBOTTOMRIGHT
                return;
            }
        }
        base.WndProc(ref m);
}

I also removed line 147 in FormBase.cs, because my Form had rounded edges
//SetWindowRegion(m.HWnd, 0, 0, pos.cx, pos.cy);

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!