在控件可见之前在 OnPaint 中更新控件的外观

Update a Control’s Appearance in OnPaint Before it is Made Visible

我有一个带有控件(按钮、面板和用户控件)的窗体,这些控件的外观有所修改,例如圆角。我根据用户的输入更改了这些控件的可见性 属性。

问题是当我使这些控件之一可见时,首先显示控件的默认版本,然后调用 OnPaint 并更新外观。例如,如果我有一个带圆角的面板,当我第一次将面板的可见性 属性 设置为 true 时,面板显示为带有尖角,然后它会更新为我编程的圆角。控件的默认外观只显示了片刻,但结果感觉不专业。

当我调试代码时,我看到一旦控件的可见性 属性 设置为 true,就会显示默认外观。接下来执行当前方法中的剩余代码。然后调用OnPaint,显示我编写的自定义外观。

我创建了一些示例代码来演示这一点:

private void Form1_Load(object sender, EventArgs e)
{
    this.BackColor = Color.LightGray;
    myPanel1.BackColor = Color.Black;
}

private void btnChangeVisibility_Click(object sender, EventArgs e)
{
    if (myPanel1.Visible)
    {
        myPanel1.Visible = false;
    }
    else
    {
        myPanel1.Visible = true;

        // Thread sleep to simulate other work being done.
        Thread.Sleep(100);
    }
}
public class MyPanel : Panel
{
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        int cornerRadius = 10;

        Rectangle rctTopLeft = new Rectangle(0, 0, cornerRadius, cornerRadius);
        Rectangle rctTopRight = new Rectangle(e.ClipRectangle.Size.Width - cornerRadius, 0, cornerRadius, cornerRadius);
        Rectangle rctBottomLeft = new Rectangle(0, e.ClipRectangle.Size.Height - cornerRadius, cornerRadius, cornerRadius);
        Rectangle rctBottomRight = new Rectangle(e.ClipRectangle.Size.Width - cornerRadius, e.ClipRectangle.Size.Height - cornerRadius, cornerRadius, cornerRadius);

        e.Graphics.FillRectangle(new SolidBrush(Color.LightGray), rctTopLeft);
        e.Graphics.FillRectangle(new SolidBrush(Color.LightGray), rctTopRight);
        e.Graphics.FillRectangle(new SolidBrush(Color.LightGray), rctBottomLeft);
        e.Graphics.FillRectangle(new SolidBrush(Color.LightGray), rctBottomRight);

        rctTopLeft = new Rectangle(rctTopLeft.Location.X, rctTopLeft.Location.Y, 2 * cornerRadius, 2 * cornerRadius);
        rctTopRight = new Rectangle(rctTopRight.Location.X - cornerRadius - 1, rctTopRight.Location.Y, 2 * cornerRadius, 2 * cornerRadius);
        rctBottomLeft = new Rectangle(rctBottomLeft.Location.X, rctBottomLeft.Location.Y - cornerRadius - 1, 2 * cornerRadius, 2 * cornerRadius);
        rctBottomRight = new Rectangle(rctBottomRight.Location.X - cornerRadius - 1, rctBottomRight.Location.Y - cornerRadius - 1, 2 * cornerRadius, 2 * cornerRadius);

        Color clr;
        clr = Color.Black;

        e.Graphics.FillPie(new SolidBrush(clr), rctTopLeft, 180, 90);
        e.Graphics.FillPie(new SolidBrush(clr), rctTopRight, 270, 90);
        e.Graphics.FillPie(new SolidBrush(clr), rctBottomLeft, 90, 90);
        e.Graphics.FillPie(new SolidBrush(clr), rctBottomRight, 0, 90);
    }
}

有什么办法可以防止这种行为吗?在将可见性 属性 设置为 true 之前,我研究过尝试更新控件的外观,但我想不出一种方法来在控件的可见性 属性 为 false 时调用 OnPaint。

我也尝试按照类似问题的答案进行操作 但我不知道如何进行这项工作,因为在暂停绘图更新时我无法调用 OnPaint。

如有任何帮助,我们将不胜感激。

在其构造函数中为您的控件启用 double buffering

public class MyPanel : Panel
{

    public MyPanel()
    {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.DoubleBuffer, true);
    } 

    // ... other code ...

}