我需要在调整大小后重绘控件,而不是在调整大小时重绘控件,因为重绘控件需要花费大量时间并且会浪费大量资源。
我的控件继承了Control类,并且我覆盖了OnResize事件。
PS: OnSizeChanged 完全一样
让我提出这个问题的另一种观点:
问题不一定是“用户仍在调整控件的大小”。真正的问题是控件的大小调整比重绘所需的时间更频繁。
如果您将问题定义为吞吐量之一,则它变得更容易解决。事实上,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();
}
}
这里的想法是让控件主动配置自己;如果您在慢速机器上运行它,或者机器只是运行缓慢,那么这将减慢它的重绘速度。如果您在尖端硬件上运行它,那么它可能根本不需要跳过任何重绘。这实际上是您在设备模拟器中经常看到的那种相当简单的“自动跳帧”算法。
To be clear, I have nothing against the approach advocated by nobugz; the only reason I would choose this one instead is that the logic is completely self-contained, whereas exposing a Resizing
property (or perhaps a more aptly-named EnableFullPaint
) is depending on the consumer to know and use it properly - and also, it prevents any repainting for the entire duration of the resize, which may cause the app to "feel" buggy - users don't tend to expect a blank/nonsense screen during a resize operation.
I've used both methods and they both work; which one is best for you depends on your requirements. I suggest you try this, see how well it works for you, and if it becomes problematic or isn't what you want then go with nobugz' answer.
只有在父控件/表单完成调整大小后,一种解决方案才能调整控件的大小。您可以使用“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");
}
当你得到 MouseDown 事件时怎么样: YourControl.SuspendLayout();
然后在 MouseUp 事件中运行:YourControl.ResumeLayout();
ResizeEnd 事件似乎是最好的主意,但作为替代方案,您可以有一个计时器,您可以在 resize 事件中重新启动它,并在计时器触发时重绘。只要计时器的时间相当短,比如 100 毫秒,那么您就不会太严重地注意到重绘延迟。
但另一个事件似乎是一个更好的选择......