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

发布于 2024-08-18 23:49:25 字数 190 浏览 8 评论 0原文

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

我的控件继承 Control 类,并且重写 OnResize 事件。

PS: OnSizeChanged 完全相同

I need to redraw a control after it was resized and not while it is being resized because it takes a lot of time to redraw a control and it wastes a lot of resources.

My control inherits Control class and I'm overriding the OnResize event.

PS: OnSizeChanged is absolutely the same

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

寂寞笑我太脆弱 2024-08-25 23:49:25

让我提出这个问题的另一种观点:

问题不一定是“用户仍在调整控件的大小”。真正的问题是控件大小的调整比重绘所需的时间更频繁。

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

Let me present an alternative view of this problem:

The issue is not necessarily that the "user is still resizing the control." The real issue is that the control is being resized more frequently than the time it takes to redraw.

If you define the problem as one of throughput, it becomes easier to solve. And in fact Bebop had the right idea with his answer, but I think we can do better:

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

The idea here is to have the control actively profile itself; if you run it on a slow machine or the machine is simply running sluggishly then this will slow down its redraw rate. If you're running it on bleeding-edge hardware then it may not have to skip any redraws at all. This is actually a fairly simple "auto frame skip" algorithm of the kind you often see in device emulators.

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.

柳絮泡泡 2024-08-25 23:49:25

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

One solution can be resizeing your control only after the parent control/form finished resizeing. You can do this using the 'ResizeEnd` event.

For example:

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");
}
生寂 2024-08-25 23:49:25

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

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

How about when you get the MouseDown event go:
YourControl.SuspendLayout();

and then in the MouseUp event go:
YourControl.ResumeLayout();

我乃一代侩神 2024-08-25 23:49:25

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

但另一个活动似乎是更好的选择......

ResizeEnd event seems the best idea, but as an alternative you could have a timer, which you restart in the resize event, and redraw when the timer fires. As long as the time of the timer is fairly short, say 100ms then you shouldn't notice the redraw delay too badly.

But the other event seems like a better option...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文