HowTo: avoid CAB TabWorkspace flickering

Have you ever tried putting a TabControl in a Winforms app and create a new TabPage via code? Just do a goolge-groups search and check  how many had the same annoying problem.
The problem is inside the Winforms TabControl implementation. CAB TabWorkspace is a simple wrapper of this control and it has nothing to do with the problem.

Avoid the flickering in the TabControl is achieved using the WM_SETREDRAW message (the first time I see this windows message was in delarou's blog, and surprisingly he was talking about the CAB DeckWorkspace). This windows message should be sent to the TabPage handle to “tell him” not to redraw before adding it to the TabControl (tabControl.TabPages.Add). Sending the message to the TabControl won’t have the desired results however.

A common approach would be to inherit from TabWorkspace, override OnShow and send this message before and after the base.OnShow. However we don’t have access on the inherited class to the raw TabPage that will be added.
Because of this, the solution would be to create a copy or modify the CAB TabWorkspace.  The
SetTabProperties method needs to be changed

const int WM_SETREDRAW = 0xB;

[DllImport("User32")]
static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

private void SetRedraw(IntPtr handle, bool on)
{
SendMessage(handle, WM_SETREDRAW, on ? 1 : 0, 0);
}

private void SetTabProperties(TabPage page, TabSmartPartInfo smartPartInfo)
{
page.Text = String.IsNullOrEmpty(smartPartInfo.Title) ? page.Text : smartPartInfo.Title;

try
{
// Avoid flickering
SetRedraw(page.Handle, false);
TabPage currentSelection = this.SelectedTab;
callComposerActivateOnIndexChange = false;
if (smartPartInfo.Position == TabPosition.Beginning)
{
TabPage[] pages = GetTabPages();
this.TabPages.Clear();
this.TabPages.Add(page);
this.TabPages.AddRange(pages);
}
else if (this.TabPages.Contains(page) == false)
{
this.TabPages.Add(page);
}

// Preserve selection through the operation.
this.SelectedTab = currentSelection;
// Avoid flickering
SetRedraw(page.Handle, true);
}
finally
{
callComposerActivateOnIndexChange = true;
}
}
Download CompositeUIExtensions.UI

As a final note, I plan to write the TabWorkspace hide feature. This annoyance also has to do with the TabControl implementation (kzu opened a bug and msft said it wouldn't be fixed because of compatibility issues). However, it could be workarounded writing some code on the TabWorkspace.
Stay tuned!

Published: February 27 2006

blog comments powered by Disqus