Reputation: 3045
I have a form with a custom controls, UserControls
. One of these controls is composed with other controls: TableLayoutPanel
, PictureBox
(it is inside of another UserControl
), Label
. Visually they are depicted in the following way:
As we can see in the image, the red rectangle is a UserControl
, the orange rectangles are TableLayoutPanel
, the yellow and green chairs are other UserControl
controls composed by a PictureBox
and a Label
.
The chairs (yellow and green ones) are draw dynamically. For example to draw the yellow chairs:
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;
}
}
These chairs and the yellow ones are drawn correctly. The problem appears when I want to register a passenger:
Note that when I add a passenger the controls blink. In code this what I do when I finish adding a passenger:
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).
How I can avoid this blink effect when?
I have tried the following UserControls methods:
ctlAvion.Invalidate();
ctlAvion.Update();
ctlAvion.Refresh();
but they does not work!
Thanks in advance for your help!
EDIT:
The answer given by @Idle_Mind is specific to my problem and it solved my problem with re-painting/drawing the custom controls I have designed.
Upvotes: 2
Views: 195
Reputation: 621
The flickering come from OnPaintBackground event that paints the background before paint the foreground, it has the flickering effect. You can override OnPaintBackground and just do nothing. And make it 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
}
}
Upvotes: 0
Reputation: 39142
Turn off updates with WM_SETREDRAW, update your UI, then turn them back on and refresh the Form:
// ... 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();
Upvotes: 2
Reputation: 183
The application has to recreate the whole UserControl, so you could hide your control when you press the accept button, then you modify the control and after this you show the control again. During the time, when your UserControl is hidden, you could display something like a loading screen or so.
Upvotes: 0
Reputation: 20764
Try using SuspendLayout()
before any modification to panel controls and after that call ResumeLayout()
.
Also make your controls double buffered, for example for a panel define this class and use it instead of panel
public class PanelEx : Panel
{
public PanelEx()
{
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
UpdateStyles();
}
}
Upvotes: 3