使 winform 中的所有控件失效会导致无限调用 OnPaint 方法
本文关键字:无限 调用 方法 OnPaint 失效 winform 控件 | 更新日期: 2023-09-27 18:12:51
>我有两个扩展控件。第一个称为LiveControl
,它继承自具有调整大小,旋转,移动PictureBox
,...方法。第二个称为DrawPanel
,它继承自Panel
,它意味着几个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();
}
但问题是,就像上面的代码一样,每个LiveControl
的OnPaint
都会使所有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
您可能需要对其中一些进行子类化,例如Panels
、FlowLayoutPanels
或DGVs
。事实上,只有Form
公开它,并且默认情况下只有PictureBox
打开它。
您还需要确保消除所有不必要的Invalidates
。 - 通常,只有当您在绘图中需要的数据发生变化时,您才需要Invalidate
。我在您的代码中根本没有看到任何绘图。否则,您有时可能需要调用Refresh
来消除撕裂,即"尾巴"或"痕迹"。
我根本不会处理OnPaint。我想让自定义绘画在 Paint 事件中做到这一点。
你不应该在油漆更新的情况下调用 Invalidate((。如果遇到闪烁问题,是否尝试在自定义控件和容器上将双缓冲设置为 true?
如果通过调用 DrawPanel.Invalidate(( 使 DrawPanel 失效,则一个覆盖具有一个名为 bool invalidateChildren
的标志。您是否尝试过将其设置为真?
希望这会有所帮助。