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 :
DrawMode
, ShowToolTip
etc..)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 ?
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.
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 !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With