1

我需要在调整大小后重绘控件,而不是在调整大小时重绘控件,因为重绘控件需要花费大量时间并且会浪费大量资源。

我的控件继承了Control类,并且我覆盖了OnResize事件。

PS: OnSizeChanged 完全一样

4

4 回答 4

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();
    }
}

这里的想法是让控件主动配置自己;如果您在慢速机器上运行它,或者机器只是运行缓慢,那么这将减慢它的重绘速度。如果您在尖端硬件上运行它,那么它可能根本不需要跳过任何重绘。这实际上是您在设备模拟器中经常看到的那种相当简单的“自动跳帧”算法。

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.

于 2010-01-24T19:25:53.393 回答
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");
}
于 2010-01-24T16:39:50.653 回答
2

当你得到 MouseDown 事件时怎么样: YourControl.SuspendLayout();

然后在 MouseUp 事件中运行:YourControl.ResumeLayout();

于 2010-01-24T16:59:28.317 回答
0

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

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

于 2010-01-24T17:30:45.153 回答