繁体   English   中英

使 Winform 中的所有控件无效会导致无限调用 OnPaint 方法

[英]Invalidating all controls in a winform causes infinite calls of OnPaint method

我有两个扩展控件。 第一个称为LiveControl ,它继承自具有调整大小、旋转、移动...方法的PictureBox 第二个叫做DrawPanel ,它是从Panel继承的,它是几个LiveControl的父LiveControl

当一个LiveControl移到另一个LiveControl时,我做了几件事来减少闪烁并留下痕迹。 最后,我使用LiveControl的以下代码实现了比我预期的更好的效果:

MouseUp += (s, e) =>
{
    foreach (Control c in Parent.Controls.OfType<LiveControl>())
        c.Refresh();
};
MouseMove += (s, e) =>
{
    if (e.Button == MouseButtons.Left)
    {
        Control x = (Control)s;
        x.SuspendLayout();
        x.Location = new Point(x.Left + e.X - cur.X, x.Top + e.Y - cur.Y);
        x.ResumeLayout();
        foreach (Control c in Parent.Controls.OfType<LiveControl>())
            c.Update();
    }
};

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    foreach (Control c in Parent.Controls.OfType<LiveControl>())                
        c.Invalidate();                    
}

但问题是,在上面的代码中,每个LiveControlOnPaint使所有LiveControl都无效,它会导致对OnPaint无限调用,从而导致表单上的其他控件出现问题(它们的工作速度非常慢且有延迟)。

为了解决这个问题,我像这样编辑了OnPaint的代码:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    if (!((DrawPanel)Parent).Invalidating)
    {
        ((DrawPanel)Parent).Invalidating = true;
        ((DrawPanel)Parent).InvalidatedCount = 0;
        foreach (Control c in Parent.Controls.OfType<LiveControl>())                
            c.Invalidate();            
    }
    else
    {
        ((DrawPanel)Parent).InvalidatedCount++;
        if (((DrawPanel)Parent).InvalidatedCount == ((DrawPanel)Parent).Controls.OfType<LiveControl>().Count())
        { 
            ((DrawPanel)Parent).InvalidatedCount = 0; ((DrawPanel)Parent).Invalidating = false;  
        }
    }
}

但是OnPaint方法仍在不停地调用。 有谁知道如何解决这个问题?

Invalidate触发Paint Paint调用Invalidate是一个无限循环。 不要那样做!

如果所有显示它的控件都DoubleBuffering ,则闪烁将消失。 请注意,要打开DoublBuffering您可能需要对其中一些进行子类化,例如PanelsFlowLayoutPanelsDGVs .. 事实上,只有Form公开它,并且默认情况下只有PictureBox将其打开。

您还需要确保消除所有不必要的Invalidates - 通常只有在绘图中需要的数据发生变化时才需要Invalidate 我在您的代码中根本看不到任何绘图。 否则,您有时可能需要调用Refresh来消除撕裂,即“尾部”或“痕迹”。

我根本不会处理 OnPaint。 我想在 Paint 事件中自定义绘制。

在绘制更新的情况下,您永远不应该调用 Invalidate()。 如果您遇到闪烁问题,是否尝试在自定义控件和容器上将 DoubleBuffered 设置为 true?

如果您通过调用 DrawPanel.Invalidate() 使 DrawPanel 无效,则覆盖有一个名为bool invalidateChildren的标志。 您是否尝试将其设置为 true?

希望这会有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM