我有一个包含自定义控件的表单UserControls
。其中一个控件由其他控件组成:TableLayoutPanel
,PictureBox
(它位于另一个UserControl
内),Label
。在视觉上,它们以下列方式描述:
正如我们在图片中看到的那样,红色矩形是UserControl
,橙色矩形是TableLayoutPanel
,黄色和绿色椅子是由{{UserControl
组成的其他PictureBox
控件1}}和Label
。
椅子(黄色和绿色)是动态绘制的。例如,绘制黄色椅子:
private void DibujarSillasEconomicas()
{
Silla[] cheapChairs = m_avion.GetCheapChairs();
Silla silla;
byte fila_silla = 0;
byte col_silla = 0;
ControlVisualChair ctlSillaGrafica;
for(int num_silla = 0; num_silla < cheapChairs.Length; ++num_silla)
{
silla = cheapChairs[num_silla];
ctlSillaGrafica = new ControlSillaGrafica(silla);
ctlSillaGrafica.Dock = DockStyle.Fill;
ctlSillaGrafica.BackColor = Color.Black;
if (num_silla > 0 & num_silla % 6 == 0)
{
++fila_silla;
col_silla = 0;
}
tplSillasEconomicas.Controls.Add(ctlSillaGrafica, col_silla == 3? ++col_silla : col_silla, fila_silla);
++col_silla;
}
}
正确绘制这些椅子和黄色椅子。当我想要登记乘客时出现问题:
请注意,当我添加乘客时,控件会闪烁。在代码中,这是我在添加乘客时所做的事情:
this.Controls.Remove(ctlAvion); // Removes the actual UserControl (red rectangle)
ctlAvion = new ControlAvion(m_avion); // Creates a new one
ctlAvion.Location = new Point(2, 13);
ctlAvion.Size = new Size(597, 475);
this.Controls.Add(ctlAvion); // Adds the new UserControl to the main controls (a Form).
我怎样才能避免这种眨眼效应?
我尝试过以下UserControls方法:
ctlAvion.Invalidate();
ctlAvion.Update();
ctlAvion.Refresh();
但它们不起作用!
提前感谢您的帮助!
编辑:
@Idle_Mind给出的答案特定于我的问题,它解决了我重新绘制/绘制我设计的自定义控件的问题。
答案 0 :(得分:3)
在对面板控件进行任何修改之前以及之后调用SuspendLayout()
之前,请尝试使用ResumeLayout()
。
还可以对控件进行双缓冲,例如,对于面板定义此类并使用它而不是面板
public class PanelEx : Panel
{
public PanelEx()
{
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
UpdateStyles();
}
}
答案 1 :(得分:2)
使用WM_SETREDRAW关闭更新,更新您的UI,然后重新打开它们并刷新表单:
// ... at Form level ...
private const int WM_SETREDRAW = 11;
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
// ... some method ...
SendMessage(this.Handle, WM_SETREDRAW, false, 0); // turn updates off
this.Controls.Remove(ctlAvion); // Removes the actual UserControl (red rectangle)
ctlAvion = new ControlAvion(m_avion); // Creates a new one
ctlAvion.Location = new Point(2, 13);
ctlAvion.Size = new Size(597, 475);
this.Controls.Add(ctlAvion); // Adds the new UserControl to the main controls (a Form).
SendMessage(this.Handle, WM_SETREDRAW, true, 0); // turn updates back on
this.Invalidate();
this.Refresh();
答案 2 :(得分:0)
应用程序必须重新创建整个UserControl,因此您可以在按下“接受”按钮时隐藏控件,然后修改控件,然后再次显示控件。 在此期间,当您的UserControl被隐藏时,您可以显示类似加载屏幕的内容。
答案 3 :(得分:0)
闪烁来自OnPaintBackground事件,它在绘制前景之前绘制背景,它具有闪烁效果。 您可以覆盖OnPaintBackground而不执行任何操作。并使其成为DoubleBuffered。
public class FlickerFreePanel : System.Windows.Forms.Panel
{
public FlickerFreePanel()
{
this.DoubleBuffered = true;
}
protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e)
{
if (this.DesignMode)
{
base.OnPaintBackground(e);
}
// Do nothing
}
}