You should avoid calling Refresh in a loop. The UI is blocked for the duration of the animation.
1. create timer that fires at the desired animation frame rate.
2. timer delegate updates the percentage and trigger a re-paint of the window.
3. cancel the timer at the end of the animation.
4. use Invalidate, not Refresh.
5. Add the following to the parent form window constructor AND the constructor of your class that derives from tableLayoutPanel:
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
I've tested this. It works. You will see a tiny amount of wiggle (but no flicker) in one or more vertical grid lines. This caused by rounding errors in the percentage driven resizing of the columns.
public partial class Form1 : Form
{
private Timer timer = new Timer();
float move = -1.0f;
public Form1()
{
InitializeComponent();
timer.Tick += new EventHandler(timer_Tick);
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
}
private void Form1_Load(object sender, EventArgs e)
{
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
tableLayoutPanel1.ColumnStyles[0].Width += move;
if (tableLayoutPanel1.ColumnStyles[0].Width <= 0.0) move = 1.0f;
else if (tableLayoutPanel1.ColumnStyles[0].Width > 50.0) move = -1.0f;
Invalidate(true);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
timer.Stop();
}
}
class Table : System.Windows.Forms.TableLayoutPanel
{
public Table()
{
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
}
}
An alternative is to create a rubber band that animates the rectangular area that grows or shrinks. This is drawn on top of the existing controls so it does not require a repaint of the area.