Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Treeview Flickering without any events

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 ?

like image 698
phadaphunk Avatar asked Oct 19 '25 10:10

phadaphunk


2 Answers

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.

like image 111
phadaphunk Avatar answered Oct 21 '25 23:10

phadaphunk


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 !

like image 45
Julien Avatar answered Oct 21 '25 23:10

Julien