在控件可见之前在 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 ...
}
我有一个带有控件(按钮、面板和用户控件)的窗体,这些控件的外观有所修改,例如圆角。我根据用户的输入更改了这些控件的可见性 属性。
问题是当我使这些控件之一可见时,首先显示控件的默认版本,然后调用 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 ...
}