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 处理事件的方式造成的。
不确定标题是否有意义。 我有一个包含多个面板的表单,每个面板都有一个与之关联的表单。 我将此表单称为“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 处理事件的方式造成的。