【发布时间】:2010-01-24 16:29:03
【问题描述】:
我需要在调整大小后重绘控件,而不是在调整大小时重绘控件,因为重绘控件需要大量时间并且浪费大量资源。
我的控件继承了 Control 类,并且我将覆盖 OnResize 事件。
PS: OnSizeChanged 完全一样
【问题讨论】:
标签: c# events controls resize redraw
我需要在调整大小后重绘控件,而不是在调整大小时重绘控件,因为重绘控件需要大量时间并且浪费大量资源。
我的控件继承了 Control 类,并且我将覆盖 OnResize 事件。
PS: OnSizeChanged 完全一样
【问题讨论】:
标签: c# events controls resize redraw
当你得到 MouseDown 事件时怎么样: YourControl.SuspendLayout();
然后在 MouseUp 事件中执行: YourControl.ResumeLayout();
【讨论】:
让我提出这个问题的另一种观点:
问题不一定是“用户仍在调整控件的大小”。真正的问题是控件调整大小的频率比重绘所需的时间更频繁。
如果您将问题定义为吞吐量之一,它会变得更容易解决。事实上,Bebop 的回答是正确的,但我认为我们可以做得更好:
public class MyControl : Control
{
private TimeSpan paintTime = 250; // Time to paint, default=250ms
private TimeSpan resizeTime = 100; // Time to update layout, default=100ms
protected override void OnPaint(PaintEventArgs pe)
{
Stopwatch sw = new Stopwatch();
sw.Start();
// Do your painting here, or call base.OnPaint
sw.Stop();
paintTime = sw.Elapsed;
}
protected override void OnResize(EventArgs e)
{
// The "Stop" is not redundant - it will force the timer to "reset"
// if it is already running.
resizeTimer.Stop();
base.OnResize(e);
resizeTimer.Interval =
(int)(paintTime.TotalMilliseconds + resizeTime.TotalMilliseconds);
resizeTimer.Start();
}
private void UpdateSize()
{
Stopwatch sw = new Stopwatch();
sw.Start();
// Resizing code goes here
sw.Stop();
resizeTime = sw.Elapsed;
}
private void resizeTimer_Tick(object sender, EventArgs e)
{
resizeTimer.Stop();
UpdateSize();
}
}
这里的想法是让控件主动配置自己;如果您在慢速机器上运行它,或者机器只是运行缓慢,那么这将减慢它的重绘速度。如果您在尖端硬件上运行它,那么它可能根本不需要跳过任何重绘。这实际上是您在设备模拟器中经常看到的那种相当简单的“自动跳帧”算法。
需要明确的是,我并不反对 nobugz 提倡的方法;我选择这个的唯一原因是逻辑是完全独立的,而暴露Resizing 属性(或者可能更贴切地命名EnableFullPaint)取决于消费者了解和正确使用它 -而且,它可以防止在调整大小的整个过程中任何重新绘制,这可能会导致应用“感觉”有问题 - 用户在调整大小操作期间不会期望出现空白/无意义的屏幕。
我用过这两种方法,它们都有效;哪一个最适合您取决于您的要求。我建议你试试这个,看看它对你的效果如何,如果它变得有问题或者不是你想要的,那么请使用 nobugz 的答案。
【讨论】:
只有在父控件/窗体完成调整大小后,才能调整控件的大小。您可以使用“ResizeEnd”事件来做到这一点。
例如:
private void UserControl1_Load(object sender, EventArgs e)
{
((Form)this.Parent).ResizeEnd += new EventHandler(UserControl1_ResizeEnd);
}
void UserControl1_ResizeEnd(object sender, EventArgs e)
{
MessageBox.Show("Resize end");
}
【讨论】:
ResizeEnd 事件似乎是最好的主意,但作为替代方案,您可以有一个计时器,您可以在 resize 事件中重新启动它,并在计时器触发时重绘。只要计时器的时间相当短,比如 100 毫秒,那么您应该不会太严重地注意到重绘延迟。
但其他活动似乎是更好的选择......
【讨论】: