winforms 无边框窗体调整大小闪烁

vmjh9lq9  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(251)

我花了几个小时在无边框表单上,我已经能够从它那里得到我需要的所有功能。唯一困扰我的是当从顶部、左上角或者离开,窗体会在对面闪烁。组件也会闪烁,但我想出了如何处理这个问题。现在我我专注于试图让闪烁停止,同时保持无边框形式完全无边框。我知道这个问题源于形式绘制移动的距离,然后重新绘制大小(或反之亦然),但我不能让它停止。
我尝试了几种不同的方法来调整窗体大小,从使用PInvokeWndProc方法到只设置窗体的位置当我改变位置和大小时试图锁定窗体。似乎没有什么能消除这种闪烁,除非我使用的是一个相当大的窗体。我可以隐藏大部分相当大的窗体,但仍然有几个像素的标题栏离开。我在搜索时发现的每一种方法都产生了相同的结果。
以下是我目前在Main Form上用来继承的内容:

using System.Drawing;
using System.Windows.Forms;

namespace TestBorderlessModernGUI
{
    /// <summary>
    /// Inherit from EdgeDrag in the main form
    /// </summary>
    public class EdgeDrag : Form
    {
        protected bool isDragging = false;
        protected bool canDrag = false;
        protected Rectangle lastRectangle = new Rectangle();

        public EdgeDrag()
        {
        }

        /// <summary>
        /// Call after component Initialization in the Main Form
        /// </summary>
        protected void InitialiseFormEdge()
        {
            int resizeWidth = 2;

            this.MouseDown += new MouseEventHandler(form_MouseDown);
            this.MouseMove += new MouseEventHandler(form_MouseMove);
            this.MouseUp += new MouseEventHandler(form_MouseUp);

            // bottom
            UserControl uc1 = new UserControl()
            {
                Anchor = (AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right),
                Height = resizeWidth,
                Width = this.DisplayRectangle.Width - (resizeWidth * 2),
                Left = resizeWidth,
                Top = this.DisplayRectangle.Height - resizeWidth,
                BackColor = Color.Transparent,
                Cursor = Cursors.SizeNS
            };
            uc1.MouseDown += form_MouseDown;
            uc1.MouseUp += form_MouseUp;
            uc1.MouseMove += delegate (object sender, MouseEventArgs e)
            {
                if (isDragging)
                {
                    this.Size = new Size(lastRectangle.Width, e.Y - lastRectangle.Y + this.Height);
                }
            };
            uc1.BringToFront();

            this.Controls.Add(uc1);
            this.Controls.SetChildIndex(uc1, 0);

            // right
            UserControl uc2 = new UserControl()
            {
                Anchor = (AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom),
                Height = this.DisplayRectangle.Height - (resizeWidth * 2),
                Width = resizeWidth,
                Left = this.DisplayRectangle.Width - resizeWidth,
                Top = resizeWidth,
                BackColor = Color.Transparent,
                Cursor = Cursors.SizeWE
            };
            uc2.MouseDown += form_MouseDown;
            uc2.MouseUp += form_MouseUp;
            uc2.MouseMove += delegate (object sender, MouseEventArgs e)
            {
                if (isDragging)
                {
                    this.Size = new Size(e.X - lastRectangle.X + this.Width, lastRectangle.Height);
                }
            };
            uc2.BringToFront();

            this.Controls.Add(uc2);
            this.Controls.SetChildIndex(uc2, 0);

            // bottom-right
            UserControl uc3 = new UserControl()
            {
                Anchor = (AnchorStyles.Bottom | AnchorStyles.Right),
                Height = resizeWidth,
                Width = resizeWidth,
                Left = this.DisplayRectangle.Width - resizeWidth,
                Top = this.DisplayRectangle.Height - resizeWidth,
                BackColor = Color.Transparent,
                Cursor = Cursors.SizeNWSE
            };
            uc3.MouseDown += form_MouseDown;
            uc3.MouseUp += form_MouseUp;
            uc3.MouseMove += delegate (object sender, MouseEventArgs e)
            {
                if (isDragging)
                {
                    this.Size = new Size((e.X - lastRectangle.X + this.Width), (e.Y - lastRectangle.Y + this.Height));
                }
            };
            uc3.BringToFront();

            this.Controls.Add(uc3);
            this.Controls.SetChildIndex(uc3, 0);

            // top-right
            UserControl uc4 = new UserControl()
            {
                Anchor = (AnchorStyles.Top | AnchorStyles.Right),
                Height = resizeWidth,
                Width = resizeWidth,
                Left = this.DisplayRectangle.Width - resizeWidth,
                Top = 0,
                BackColor = Color.Transparent,
                Cursor = Cursors.SizeNESW
            };
            uc4.MouseDown += form_MouseDown;
            uc4.MouseUp += form_MouseUp;
            uc4.MouseMove += delegate (object sender, MouseEventArgs e)
            {
                if (isDragging)
                {
                    int diff = (e.Location.Y - lastRectangle.Y);
                    int y = (this.Location.Y + diff);

                    this.Location = new Point(this.Location.X, y);
                    this.Size = new Size(e.X - lastRectangle.X + this.Width, (this.Height + (diff * -1)));
                }
            };
            uc4.BringToFront();
            //uc4.BackColor = Color.Firebrick;

            this.Controls.Add(uc4);
            this.Controls.SetChildIndex(uc4, 0);

            // top
            UserControl uc5 = new UserControl()
            {
                Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right),
                Height = resizeWidth,
                Width = this.DisplayRectangle.Width - (resizeWidth * 2),
                Left = resizeWidth,
                Top = 0,
                BackColor = Color.Transparent,
                Cursor = Cursors.SizeNS
            };
            uc5.MouseDown += form_MouseDown;
            uc5.MouseUp += form_MouseUp;
            uc5.MouseMove += delegate (object sender, MouseEventArgs e)
            {
                if (isDragging)
                {
                    int diff = (e.Location.Y - lastRectangle.Y);
                    int y = (this.Location.Y + diff);

                    this.Location = new Point(this.Location.X, y);
                    this.Size = new Size(lastRectangle.Width, (this.Height + (diff * -1)));

                }
            };
            uc5.BringToFront();

            this.Controls.Add(uc5);
            this.Controls.SetChildIndex(uc5, 0);

            // left
            UserControl uc6 = new UserControl()
            {
                Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom),
                Height = this.DisplayRectangle.Height - (resizeWidth * 2),
                Width = resizeWidth,
                Left = 0,
                Top = resizeWidth,
                BackColor = Color.Transparent,
                Cursor = Cursors.SizeWE
            };
            uc6.MouseDown += form_MouseDown;
            uc6.MouseUp += form_MouseUp;
            uc6.MouseMove += delegate (object sender, MouseEventArgs e)
            {
                if (isDragging)
                {
                    int diff = (e.Location.X - lastRectangle.X);
                    int x = (this.Location.X + diff);

                    this.Location = new Point(x, this.Location.Y);
                    this.Size = new Size((this.Width + (diff * -1)), this.Height);
                }
            };
            uc6.BringToFront();

            this.Controls.Add(uc6);
            this.Controls.SetChildIndex(uc6, 0);

            // bottom-left
            UserControl uc7 = new UserControl()
            {
                Anchor = (AnchorStyles.Bottom | AnchorStyles.Left),
                Height = resizeWidth,
                Width = resizeWidth,
                Left = 0,
                Top = this.DisplayRectangle.Height - resizeWidth,
                BackColor = Color.Transparent,
                Cursor = Cursors.SizeNESW
            };
            uc7.MouseDown += form_MouseDown;
            uc7.MouseUp += form_MouseUp;
            uc7.MouseMove += delegate (object sender, MouseEventArgs e)
            {
                if (isDragging)
                {
                    int diff = (e.Location.X - lastRectangle.X);
                    int x = (this.Location.X + diff);

                    this.Location = new Point(x, this.Location.Y);
                    this.Size = new Size((this.Width + (diff * -1)), (e.Y - lastRectangle.Y + this.Height));
                }
            };
            uc7.BringToFront();

            this.Controls.Add(uc7);
            this.Controls.SetChildIndex(uc7, 0);

            // bottom-left
            UserControl uc8 = new UserControl()
            {
                Anchor = (AnchorStyles.Top | AnchorStyles.Left),
                Height = resizeWidth,
                Width = resizeWidth,
                Left = 0,
                Top = 0,
                BackColor = Color.Transparent,
                Cursor = Cursors.SizeNWSE
            };
            uc8.MouseDown += form_MouseDown;
            uc8.MouseUp += form_MouseUp;
            uc8.MouseMove += delegate (object sender, MouseEventArgs e)
            {
                if (isDragging)
                {
                    int dX = (e.Location.X - lastRectangle.X);
                    int dY = (e.Location.Y - lastRectangle.Y);
                    int x = (this.Location.X + dX);
                    int y = (this.Location.Y + dY);

                    this.Location = new Point(x, y);
                    this.Size = new Size((this.Width + (dX * -1)), (this.Height + (dY * -1)));
                }
            };
            uc8.BringToFront();

            this.Controls.Add(uc8);
            this.Controls.SetChildIndex(uc8, 0);
        }

        private void form_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isDragging = true;
                lastRectangle = new Rectangle(e.Location.X, e.Location.Y, this.Width, this.Height);

                // If the mouse is within the dragging area
                if (e.Y <= 30 && e.X <= this.Size.Width - 120)
                    canDrag = true;
            }
        }

        private void form_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                // If we can drag the form
                if (canDrag)
                {
                    int x = (this.Location.X + (e.Location.X - lastRectangle.X));
                    int y = (this.Location.Y + (e.Location.Y - lastRectangle.Y));
                    this.Location = new Point(x, y);
                }
            }
        }

        private void form_MouseUp(object sender, MouseEventArgs e)
        {
            if (isDragging)
                isDragging = false;

            if (canDrag)
                canDrag = false;
        }
    }
}

有没有人知道一种方法来摆脱闪烁的无边界的形式边缘,使它类似于大小相当的形式?

**编辑:**我已经修改了代码,使用WndProc来调整大小,就像Jimi说的那样,它仍然像其他代码一样闪烁。我开始认为停止闪烁的唯一方法是使用一个可调大小的窗体。有人有什么想法吗?

表单构造器:

public MainForm()
{
    InitializeComponent();
    this.FormBorderStyle = FormBorderStyle.None;
    this.DoubleBuffered = true;
    this.SetStyle(ControlStyles.ResizeRedraw, true);
}

调整边缘大小代码:

private const int HTLEFT = 10,
                          HTRIGHT = 11,
                          HTTOP = 12,
                          HTTOPLEFT = 13,
                          HTTOPRIGHT = 14,
                          HTBOTTOM = 15,
                          HTBOTTOMLEFT = 16,
                          HTBOTTOMRIGHT = 17,
                          HTCAPTION = 2;

        const int edgeSize = 3; // you can rename this variable if you like

        Rectangle Top { get { return new Rectangle(0, 0, this.ClientSize.Width, edgeSize); } }
        Rectangle Left { get { return new Rectangle(0, 0, edgeSize, this.ClientSize.Height); } }
        Rectangle Bottom { get { return new Rectangle(0, this.ClientSize.Height - edgeSize, this.ClientSize.Width, edgeSize); } }
        Rectangle Right { get { return new Rectangle(this.ClientSize.Width - edgeSize, 0, edgeSize, this.ClientSize.Height); } }

        Rectangle TopLeft { get { return new Rectangle(0, 0, edgeSize, edgeSize); } }
        Rectangle TopRight { get { return new Rectangle(this.ClientSize.Width - edgeSize, 0, edgeSize, edgeSize); } }
        Rectangle BottomLeft { get { return new Rectangle(0, this.ClientSize.Height - edgeSize, edgeSize, edgeSize); } }
        Rectangle BottomRight { get { return new Rectangle(this.ClientSize.Width - edgeSize, this.ClientSize.Height - edgeSize, edgeSize, edgeSize); } }

        protected override CreateParams CreateParams { get { var cp = base.CreateParams; cp.ExStyle |= 0x02000000; return cp; } }
        protected override void OnPaint(PaintEventArgs e)
        {
            if (this.WindowState == FormWindowState.Normal)
            {
                Rectangle rc = new Rectangle(this.ClientSize.Width - cGrip, this.ClientSize.Height - cGrip, cGrip, cGrip);
                ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
            }
        }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            if (m.Msg == 0x84)
            {  // Trap WM_NCHITTEST
                var cursor = this.PointToClient(Cursor.Position);

                if (TopLeft.Contains(cursor)) m.Result = (IntPtr)HTTOPLEFT;
                else if (TopRight.Contains(cursor)) m.Result = (IntPtr)HTTOPRIGHT;
                else if (BottomLeft.Contains(cursor)) m.Result = (IntPtr)HTBOTTOMLEFT;
                else if (BottomRight.Contains(cursor)) m.Result = (IntPtr)HTBOTTOMRIGHT;
                else if (Top.Contains(cursor)) m.Result = (IntPtr)HTTOP;
                else if (Left.Contains(cursor)) m.Result = (IntPtr)HTLEFT;
                else if (Right.Contains(cursor)) m.Result = (IntPtr)HTRIGHT;
                else if (Bottom.Contains(cursor)) m.Result = (IntPtr)HTBOTTOM;
                else if (cursor.Y < cCaption) m.Result = (IntPtr)HTCAPTION;
            }
        }
csga3l58

csga3l581#

我觉得自己很蠢。
我可以用下面的方法让闪烁停止...
1.我切换到WndProc来调整大小和拖动,就像我上面的编辑一样
1.我正在使用FixedSingle而不是None作为窗体边框样式。从技术上讲,它不是一个无边框窗口,但当将Text设置为空并将ControlBox设置为false时,它具有我正在寻找的行为。
除了上面修改过的代码之外,我的构造函数现在看起来如下:

public MainForm()
        {
            InitializeComponent();
            this.FormBorderStyle = FormBorderStyle.FixedSingle;
            this.Text = string.Empty;
            this.ControlBox = false;
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
        }

正如您在此图像中所看到的,窗口的行为就像可调整大小的窗口一样,在相对的边缘上没有跳跃或闪烁。

**编辑:**我遇到的另一个问题是在任务栏和任务管理器中给窗口命名。我可以用修改过的CreateParams getter来完成这个任务。修改的部分是cp.Style值和cp. Caption。cp.Style &= ~0xC00000行隐藏了标题栏,cp.Style |= 0x00800000显示了一个细线边框,这是使用此方法时防止闪烁所必需的,cp.Caption = "TEST"然后在任务栏和任务管理器中设置标题。

protected override CreateParams CreateParams 
{ 
    get 
    { 
        new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();

        // Extend the CreateParams property of the Button class.
        var cp = base.CreateParams;
        // Update the button Style.
        cp.Style &= ~0xC00000; //WS_CAPTION;
        cp.Style |= 0x00800000;
        cp.ExStyle |= 0x02000000;
        cp.Caption = "TEST";

        return cp; 
    } 
}

相关问题