C# Windows Forms: Splitter flickering

﹥>﹥吖頭↗ 提交于 2019-12-24 17:54:53

问题


I have the following problem: I placed a splitter-control (not split-container) in my form and added 2 panels. The splitter works properly but when I move the splitter, it starts to flicker - the panels dont.

I get the same result with a Split-Container.

I tried this but nothing works

this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.DoubleBuffered = true;
...


class XSplitter : Splitter
{
    public XSplitter() : base()
    {
        this.SetStyle(ControlStyles.UserPaint, true);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.DoubleBuffer, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.DoubleBuffered = true;
    }
}

class XPanel : Panel
{
    public XPanel() : base()
    {
        this.SetStyle(ControlStyles.UserPaint, true);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.DoubleBuffer, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.DoubleBuffered = true;
    }
}

I use Windows 8.1 and VS 2010

Thx for help!


回答1:


Here are the steps to use this control:

  • Add new class "NonFlickerSplitContainer" to your C# application.
  • Replace auto generated class code with C# code shown below.
  • Use NonFlickerSplitContainer object instead of SplitContainer object in your application.

    public partial class NonFlickerSplitContainer : SplitContainer
    {
       public NonFlickerSplitContainer()
       {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint |
                      ControlStyles.UserPaint |
                      ControlStyles.OptimizedDoubleBuffer, true);
    
        MethodInfo objMethodInfo = typeof(Control).GetMethod("SetStyle",BindingFlags.NonPublic|BindingFlags.Instance);
    
        object[] objArgs = new object[] { ControlStyles.AllPaintingInWmPaint |
                                          ControlStyles.UserPaint |
                                          ControlStyles.OptimizedDoubleBuffer, true };
    
        objMethodInfo.Invoke(this.Panel1, objArgs);
        objMethodInfo.Invoke(this.Panel2, objArgs);
       }
    }
    



回答2:


Look at Splitter source code - http://referencesource.microsoft.com

  1. Splitter draws on parents' (not own) device context, using GDI calls from outside of WM_PAINT:

    private void DrawSplitHelper(int splitSize) {
      ...
      IntPtr parentHandle = ParentInternal.Handle;
      IntPtr dc = UnsafeNativeMethods.GetDCEx(new HandleRef(ParentInternal, parentHandle), NativeMethods.NullHandleRef, NativeMethods.DCX_CACHE | NativeMethods.DCX_LOCKWINDOWUPDATE);
      IntPtr halftone = ControlPaint.CreateHalftoneHBRUSH();
      ...
    

    so style setting does not have any effect.

  2. When Splitter moves, it removes image from previous position before drawing at new place:

    private void DrawSplitBar(int mode) {
      if (mode != DRAW_START && lastDrawSplit != -1) {
        DrawSplitHelper(lastDrawSplit);
        lastDrawSplit = -1;
      ...
    

    If the screen refreshes at this moment, you see flickering.

  3. Windows Forms was developed at those years, when most people used CRT monitors, and halftone brushes (vide supra) looks smooth. These days some LCD monitors flicker even on static picture.

The solution is creating of solid brush instead of halftone one:

    var brush = default(LOGBRUSH);
    brush.lbColor = 0x2A2A2A; // Invert alternate bits except highest:  ..#.#.#.

and redrawing only difference rectangle on moving:

    private void DrawSplitBar(int mode)
    {
      ...
      if (mode != DRAW_END)
      {
        var rect = newRect;
        SubtractRect(out newRect, ref newRect, ref oldRect);
        SubtractRect(out oldRect, ref oldRect, ref rect);
      }
      DrawSplitHelper(oldRect);
      ...

See my solution at https://gist.github.com/ArtemAvramenko/e260420b86564cf13d2e



来源:https://stackoverflow.com/questions/19859504/c-sharp-windows-forms-splitter-flickering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!