I needed a Control that implemented the same functionality as controls like the TreeView and ListView where you can call BeginUpdate and EndUpdate when you want to do an operation that repaints the control several times and cause flickering. So first thing I did was whip out Reflector and had a look at the TreeView.BeginUpdate(). It called Control.BeginUpdateInternal(), but this was an internal method and I did not want to invode reflection to get to it so I had a look at the code and came up with this.
Added the UnsafeNativeMethods class to call SendMessage:
[SuppressUnmanagedCodeSecurity]
internal static class UnsafeNativeMethods
{
public const int WM_SETREDRAW = 0xB;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);
}
Then I added this code to my UserControl and presto I had BeginUpdate and EndUpdate.
#region BeginUpdate And EndUpdate Added in UserControl
internal IntPtr SendMessage(int msg, int wparam, int lparam)
{
return UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), msg, wparam, lparam);
}
private short updateCount;
public void BeginUpdate()
{
if (this.IsHandleCreated)
{
if (this.updateCount == 0)
{
this.SendMessage(UnsafeNativeMethods.WM_SETREDRAW, 0, 0);
}
this.updateCount = (short)(this.updateCount + 1);
}
}
public void EndUpdate()
{
this.EndUpdate(true);
}
internal void EndUpdate(bool invalidate)
{
if (this.updateCount
{
return;
}
this.updateCount = (short)(this.updateCount - 1);
if (this.updateCount == 0)
{
this.SendMessage(UnsafeNativeMethods.WM_SETREDRAW, -1, 0);
if (invalidate)
{
this.Invalidate(true);
}
}
return;
}
#endregion
If you compare EndUpdate to the code in Control.EndUpdateInternal() you will see that I changed this.Invalidate() to this.Invalidate(true) so that all the child controls are also repainted.