簡體   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