【问题标题】:Use windows animations on borderless form在无边界表单上使用 windows 动画
【发布时间】:2015-07-17 10:14:16
【问题描述】:

最近我(主要是出于好奇)做了一个无边界的表格。在制作了包含标题和三个按钮(最小化、最大化和关闭)的自己的标题栏之后,就像每个普通的 Windows 程序一样。我还为这些按钮编写了代码(请问您是否想查看代码)。

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

有什么方法可以使用标准 Windows 程序使用的这些动画吗?

【问题讨论】:

    标签: c# winforms animation borderless


    【解决方案1】:

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

    你要做的基本上是创建一个表单,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 行,因为我的表单有圆角
    //SetWindowRegion(m.HWnd, 0, 0, pos.cx, pos.cy);

    【讨论】:

      【解决方案2】:

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

      1. 在 Minimize 或 Restore 之前将 FormBorderStyle 设置回 Sizable,然后再设置回 none。

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

      这里是一些示例代码:

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

      【讨论】:

      • 嗯,第一个解决方案似乎是一个简单的解决方法。我还将处理第二个,并会通知您。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-25
      • 1970-01-01
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多