C#Windows窗体:拆分器闪烁

C#Windows窗体:拆分器闪烁,c#,winforms,splitter,C#,Winforms,Splitter,我有以下问题:我在表单中放置了一个拆分器控件(不是拆分容器),并添加了两个面板。拆分器工作正常,但当我移动拆分器时,它开始闪烁-面板不闪烁 对于拆分容器,我得到了相同的结果 我试过了,但没用 this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.DoubleBuffer, true); th

我有以下问题:我在表单中放置了一个拆分器控件(不是拆分容器),并添加了两个面板。拆分器工作正常,但当我移动拆分器时,它开始闪烁-面板不闪烁

对于拆分容器,我得到了相同的结果

我试过了,但没用

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;
    }
}
我使用Windows8.1和VS2010


谢谢你的帮助

以下是使用此控件的步骤:

  • 将新类“NonFlickerSplitContainer”添加到C#应用程序中
  • 将自动生成的类代码替换为C#代码,如下所示
  • 在应用程序中使用非ClickerSplitContainer对象,而不是SplitContainer对象

    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);
       }
    }
    

查看拆分器源代码-

  • 拆分器使用来自WM_PAINT外部的GDI调用,利用父设备(非自有)上下文:

    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();
      ...
    
    所以样式设置没有任何效果

  • 拆分器移动时,将在新位置绘制之前从上一位置删除图像:

    private void DrawSplitBar(int mode) {
      if (mode != DRAW_START && lastDrawSplit != -1) {
        DrawSplitHelper(lastDrawSplit);
        lastDrawSplit = -1;
      ...
    
    如果此时屏幕刷新,您会看到闪烁

  • Windows窗体是在那个年代开发的,当时大多数人使用CRT显示器,半色调画笔(见上图)看起来很平滑。现在有些液晶显示器即使在静态画面上也会闪烁

  • 解决方案是创建实心笔刷,而不是半色调笔刷:

        var brush = default(LOGBRUSH);
        brush.lbColor = 0x2A2A2A; // Invert alternate bits except highest:  ..#.#.#.
    
    并在移动时仅重新绘制差异矩形:

        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);
          ...
    

    查看位于

    的我的解决方案面板上有许多控件吗?我试过使用空面板,它一点也不闪烁。我只有拆分器和窗体上的2个面板。。。是的,这很奇怪,因为我在Windows7上试过,它工作正常。。。但在家里,它看起来不像是涉及到这里的操作系统,因为我也在使用Windows 7,它工作正常,可能这是Windows 8相关问题的一部分。虽然这个链接可能会回答这个问题,但最好在这里包括答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。欢迎使用。根据,请确保您披露您与您在帖子中提到的网站的联系。谢谢我不知道如何披露从属关系,所以我将从我的帖子中删除网站链接。