如何检查调整大小是否仍在进行OnResize事件?

时间:2010-01-24 16:29:03

标签: c# events controls resize redraw

我需要在调整大小之后重新绘制一个控件,而不是在调整大小时重新调整它,因为它需要花费大量时间来重绘控件并且浪费了大量资源。

我的控件继承了 Control 类,我正在覆盖 OnResize 事件。

PS: OnSizeChanged完全相同

4 个答案:

答案 0 :(得分:8)

让我提出另一种观点:

问题不一定是“用户仍在调整控件的大小”。真正的问题是控件的重新调整次数比重绘时间更长。

如果您将问题定义为吞吐量之一,则解决起来会更容易。事实上,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的回答。

答案 1 :(得分:2)

一种解决方案是只能在父控件/完成大小调整后调整控件大小。您可以使用'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");
}

答案 2 :(得分:1)

当您获得MouseDown事件时,该怎么做: YourControl.SuspendLayout();

然后在MouseUp事件中转到: YourControl.ResumeLayout();

答案 3 :(得分:0)

ResizeEnd事件似乎是最好的主意,但作为替代方案,您可以拥有一个计时器,您可以在resize事件中重新启动,并在计时器触发时重绘。只要计时器的时间相当短,比如100毫秒,那么你就不应该注意到重绘延迟太差了。

但另一个事件似乎是一个更好的选择...