Winforms:在 windows 10 上尝试 move/Drag 时表格滞后

Winforms: Form lags when trying to move/Drag it on windows 10

不确定标题是否有意义。 我有一个包含多个面板的表单,每个面板都有一个与之关联的表单。 我将此表单称为“mainForm”,当我 move/drag 它在我的屏幕上移动时,它滞后很多,鼠标也感觉极度无响应。

当你第一次打开它时,它一点也不滞后,但是在屏幕上有一些控件后,它的滞后变得很明显,当我有超过 100 个控件时,它变得非常滞后。如果我不移动它,程序运行正常,本身一切都很好,只是当我尝试移动它时。

我不完全确定它是如何工作的,但是当您移动它时,它是否会重新计算表单和控件上的某些内容并在其中?如果是这样,是否可以在尝试移动时禁用它并在我们停止移动时重新启用它?

由于时间限制,此时无法更改为 WPF。

希望之前有人遇到过这样的问题。 非常感谢任何提示。

谢谢大家抽出时间!

我曾经在 winforms 中创建过这个:

public class FormExt : Form
    {
        /// <summary>
        ///     Required designer variable.
        /// </summary>
        private IContainer components;

       
        private readonly TableLayoutPanel tlp = new TableLayoutPanel();

        public FormExt(IFormExtension formExtension)
        {
            FormExtension = formExtension;
            InitializeComponent();
        }

        public FormExt()
        {
            InitializeComponent();
        }

        public Panel LowerLeft { get; set; }
        public BorderedPanel LowerRight { get; set; }
        public Panel UpperLeft { get; set; }

        public IFormExtension FormExtension { get; set; }

        public virtual void FormExtended_Closing(object sender, CancelEventArgs e)
        {
            if (FormExtension.Parent != null)
            {
                FormExtension.Parent.Refresh();
                FormExtension.Parent.Show();
            }
        }

        /// <summary>
        ///     Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && components != null) components.Dispose();
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        ///     Required method for Designer support - do not modify
        ///     the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            //TableLayoutPanel
            tlp.Location = new Point(0, 0);
            tlp.Dock = DockStyle.Fill;
            tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F));
            tlp.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize, 500F));
            tlp.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
            tlp.RowStyles.Add(new RowStyle(SizeType.AutoSize, 550F));
            tlp.CellBorderStyle = TableLayoutPanelCellBorderStyle.None;

            tlp.BorderStyle = BorderStyle.None;
            tlp.Margin = new Padding(0);
            tlp.Padding = new Padding(0);

            //Upper background color
            Color myRgbColor = new Color();
#if DEBUG
            myRgbColor = Color.FromArgb(255, 0, 0);
#else
            myRgbColor = Color.FromArgb(10, 19, 39);
#endif
            //LowerLeft
            LowerLeft = new Panel();
            LowerLeft.BackColor = Color.White;
            LowerLeft.Dock = DockStyle.Fill;

            //UpperLeft
            UpperLeft = new Panel();
            UpperLeft.BackColor = myRgbColor;

            UpperLeft.BackgroundImageLayout = ImageLayout.None;
            UpperLeft.Dock = DockStyle.Fill;

            //LowerRight
            LowerRight = new BorderedPanel();
            LowerRight.Size = new Size(600, 550);
            LowerRight.BackColor = Color.White;
            LowerRight.Dock = DockStyle.Fill;

            components = new System.ComponentModel.Container();
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(800, 450);
            FormClosing += FormExtended_Closing;
            Text = "";

            this.Controls.Add(tlp);
            tlp.SetColumnSpan(UpperLeft, 2);
            LowerLeft.Margin = new Padding(0);
            LowerLeft.Padding = new Padding(0);
            tlp.Controls.Add(LowerLeft, 0, 1);
            UpperLeft.Margin = new Padding(0);
            UpperLeft.Padding = new Padding(0);
            tlp.Controls.Add(UpperLeft, 0, 0);
            LowerRight.Margin = new Padding(0);
            LowerRight.Padding = new Padding(0);
            tlp.Controls.Add(LowerRight, 1, 1);
        }

        #endregion
    }

成为布局模板。 然后我会在左下角添加按钮,在右下角添加内容,在左上角和右上角添加徽标和一些可能的页面机制,如过滤器列表等。

好的概念是您一次有 1 个活动表单。虽然其他形式仍然存在于内存中,但它们保持不活动状态,除非您故意传递它们,否则不会接收事件。据我所知。至少,我从未遇到过您描述的使用此组件的问题。但是我从来没有在同一个表单上同时加载“数百个控件”。那只是……一个单一的表格要承担很多责任。

formExtension接口:

public interface IFormExtension
    {
        public Form Parent { get; set; }
    }

这只是创建多个表单的一种方法,每个表单都有自己的“table-layout”,您可以重载这个特定的布局 ->(或您自己制作的布局)

或者您可以简单地重新定义一个放置在 TableLayoutPanel 中的新布局,然后您的表单应该会按预期工作。

我终于解决了。即使 Morten Bork 共享的代码也会出现此问题。只是控件太多了(在我做的测试中我有大约 500 个控件)并且表格在移动时变得非常慢。

用户 Jimi 对此事的意见是关键,在查看事件后,我尝试了以下方法并解决了我的问题。所以希望需要类似解决方案的人可以使用我的解决方案。

在我的“mainForm”中,当它移动时,我清除了“ResizeBegin”中的主面板,并将子面板添加回“ResizeEnd”中的主面板,到目前为止它工作得很好。因为我还保存了当前显示的子面板,所以我可以先显示那个子面板。

我遇到了同样的问题,我找到了解决方法,但没有任何意义。

我覆盖了 WndProc 以查看在表单移动期间发送了哪些消息可能会减慢它的速度。移动表单时循环显示 5 条消息:

  • 3: WM_MOVE
  • 534: WM_MOVING
  • 70: WM_WINDOWPOSCHANGING
  • 36: WM_GETMINMAXINFO
  • 71: WM_WINDOWPOSCHANGED

起初,我怀疑可能需要大量控件进行大量处理的唯一 Windows 消息是 WM_GETMINMAXINFO,因为它可能正在评估控件的大小,并且需要更长的时间更多控件。

令人惊讶的是,Debug.WriteLine 语句的覆盖和添加足以完全消除延迟。

    protected override void WndProc(ref Message m)
    {
        Debug.WriteLine($"msg: {message.Msg}, wparam:{message.WParam}, lparam:{message.LParam}, lparam:{message.HWnd}");
        base.WndProc(ref m);
    }

Debug.WriteLine 语句的存在似乎改变了该方法的行为,使表单平滑移动,没有滞后。如果我在发布模式下编译或注释掉 Debug 语句,那么表单会再次滞后。意义不大。

UPDATE/SOLUTION:新信息。只有在使用我的 Rival 650 无线鼠标拖动表格时才会出现这种延迟。当我使用笔记本电脑内置的鼠标垫拖动 window 时,它不会滞后。也许鼠标驱动程序正在做一些愚蠢的事情,或者它太快地产生鼠标移动事件,并且不知何故添加调试语句会减慢速度足以破坏延迟。

如果我将鼠标的轮询速率从 1000hz 降低到 500hz,仍然存在延迟,但如果我将其降低到 250hz,则 window 拖动延迟完全消失。所以这似乎是鼠标的高 polling/event 速率和 Windows 处理事件的方式造成的。