在无边框窗体上使用Windows动画

时间:2015-07-17 10:14:16

标签: c# winforms animation borderless

最近,我(主要是出于好奇)制作了一个无国界的形式。制作我自己的标题栏,其中包括标题和三个按钮(最小化,最大化和关闭),就像每个正常的Windows程序一样。我还为这些按钮编写了代码(只是询问您是否要查看代码)。

但是,我注意到没有动画。我的意思是,例如,如果我单击最小化按钮,没有动画,程序立即消失(它不关闭,按钮工作,但没有动画)。在所有情况下都会发生这种情况:当我打开程序时会立即显示,当我关闭它时,它会立即消失。

是否有某种方法可以使用标准Windows程序使用的这些动画?

2 个答案:

答案 0 :(得分:2)

似乎无法在无边框表单上创建动画效果。但是,有两种可能的解决方法。

  1. 在最小化或恢复之前将FormBorderStyle设置回Sizable,然后再返回到无。

  2. 请改用AnimateWindow功能。动画往往发生在窗口当前所在的位置。这些功能可以应用于任何Control,而不仅仅是顶级窗口。

  3. 以下是一些示例代码:

        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);
            }
    

答案 1 :(得分:0)

我知道这个问题已在一年多前被问过,但我遇到了同样的问题并找到了一个非常好的解决方案。 看看Github的this回购。
将FormBase.cs和Native.cs添加到项目中。

你要做的就是创建一个Form,f.e。 Main.cs ,并从 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);
}

我还删除了FormBase.cs中的第147行,因为我的Form有圆角 //SetWindowRegion(m.HWnd, 0, 0, pos.cx, pos.cy);