4

I have a flickering TreeView and I know it's a common problem. The thing is the TreeView has no events.

Yes I understand that when I add the nodes recursively from a XmlDocument it flickers a little and that's normal. Mine flickers even after everything is loaded. As soon as my mouse is over a node or if I click on a node. I checked :

  • All the properties that could cause this (DrawMode, ShowToolTip etc..)
  • All events to make sure there are none. (I have a drag and drop event but I commented it too make sure it's not the problem and it doesn't change anything).
  • I used BeginUpdate and EndUpdate while the TreeView was updating. (Now it's populated and there is no process involving the TreeView but it still flickers.

Am I missing something obvious ?

phadaphunk
  • 12,785
  • 15
  • 73
  • 107

2 Answers2

5

I figured it out. It turns out to be the when a TreeView (maybe another control could have the same problem) inside a SplitContainer causes flickering problems. I tried it with a very simple prototype, a new Winform with only a SplitContainer and a TreeView inside one of the containers and I can already see the flicker on some nodes. I tried many things but what seems to have done the job is :

this.SetStyle(ControlStyles.DoubleBuffer, true);

Another thing that completely ruled out all the flickering is this :

int style = NativeWinAPI.GetWindowLong(this.Handle, NativeWindowAPI.GWL_EXSTYLE);
style |= NativeWinAPI.WS_EX_COMPOSITED;
NativeWinAPI.SetWindowLong(this.Handle, NativeWinAPI.GWL_EXSTYLE, style);

Both inside the Form_Load.

NativeWinAPI Class :

using System.Runtime.InteropServices;

internal static class NativeWinAPI
{
   internal static readonly int GWL_EXSTYLE = -20;
   internal static readonly int WS_EX_COMPOSITE = 0x02000000;

   [DllImport("user32")]
   internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32")]
   internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, dwNewLong);
}

This will totally stop the flickering for a control inside a SplitContainer. Hope I can help someone with this.

phadaphunk
  • 12,785
  • 15
  • 73
  • 107
  • 1
    No pinvoke is required, override the CreateParams property instead. – Hans Passant Dec 18 '12 at 20:47
  • Instead of my form load ? What would be the difference ? – phadaphunk Dec 18 '12 at 20:49
  • It works a treat (athough as Hans suggested I used CreateParams instead of pinvoke)! This was exactly my problem, treeview and tabcontrol in SplitContainer. The treenodes and tabpage icons were flickering quite heavily on mouseover and select. Not sure why this is not the default exstyle. Now not flicker, amaze, much wow, so happy:) – anakic Apr 11 '14 at 08:05
1

The accepted answer didn't gave me satisfaction, so I post another trick that I found here: http://dev.nomad-net.info/articles/double-buffered-tree-and-list-views

public DbTreeView()
{
    // Enable default double buffering processing (DoubleBuffered returns true)
    SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
    // Disable default CommCtrl painting on non-Vista systems
    if (Environment.OSVersion.Version.Major < 6)
        SetStyle(ControlStyles.UserPaint, true);
}

protected override void OnPaint(PaintEventArgs e)
{
    if (GetStyle(ControlStyles.UserPaint))
    {
        Message m = new Message();
        m.HWnd = Handle;
        m.Msg = WM_PRINTCLIENT;
        m.WParam = e.Graphics.GetHdc();
        m.LParam = (IntPtr)PRF_CLIENT;
        DefWndProc(ref m);
        e.Graphics.ReleaseHdc(m.WParam);
    }
    base.OnPaint(e);
}

Worked perfectly for me !

Julien
  • 1,181
  • 10
  • 31