防止在调整Windows窗体的大小时重新绘制控件

本文关键字:新绘制 绘制 控件 小时 调整 Windows 窗体 | 更新日期: 2023-09-27 18:21:00

我有一个TableLayoutPanel,它在SplitterPanel中保存了动态数量的控件。用户可能希望调整面板大小以适应这些控件,从而避免使用滚动条。这会在容器大小调整以及容器内的控件上产生抖动。有时,在调整大小的过程中,父容器明显滞后于鼠标的移动(最多滞后3秒)。

是否有任何方法可以防止在父容器调整大小期间重新绘制控件,例如在调整大小期间隐藏所有元素,或停止鼠标拖动期间发生的调整大小事件,仅在onMouseUp事件上触发?

防止在调整Windows窗体的大小时重新绘制控件

正如Hans所评论的,SuspendLayoutResumeLayout在这种情况下工作得很好,同时暂停绘制容器的控件:

public static class Win32 {
  public const int WM_SETREDRAW = 0x0b;
  [DllImport("user32.dll")]
  public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
  public static void SuspendPainting(IntPtr hWnd) {
    SendMessage(hWnd, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero);
  }
  public static void ResumePainting(IntPtr hWnd) {
    SendMessage(hWnd, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
  }
}

然后从您调整事件大小:

private void Form1_ResizeBegin(object sender, EventArgs e) {
  tableLayoutPanel1.SuspendLayout();
}
private void Form1_ResizeEnd(object sender, EventArgs e) {
  Win32.SuspendPainting(tableLayoutPanel1.Handle);
  tableLayoutPanel1.ResumeLayout();
  Win32.ResumePainting(tableLayoutPanel1.Handle);
  this.Refresh();
}

对我来说,它可以很好地实现TableLayoutPanel的双缓冲,然后我甚至不需要暂停布局。我在这个线程上找到了解决方案:如何使用这个网站的双缓冲TableLayoutPanel类来避免c#.net中的TableLayoutPanel中的闪烁:https://www.richard-banks.org/2007/09/how-to-create-flicker-free.html

在那之后,我所需要做的就是,在重建项目并重新启动Visual Studio几次(以使InitializeComponent()正常工作)之后,进入.Designer.cs文件,将System.Windows.Forms.TableLayoutPanel类更改为新的DBLayoutPanel类。进入Designer文件并更改那里的类帮助我节省了时间,因为我在TableLayoutPanel中已经有很多控件了。

您可以挂起父容器的resize事件,并将e.Handled或e.Cancel属性设置为true,然后在onMouseUp上手动重绘。