2010-07-27 84 views
12

我有一个具有背景的窗体应用程序。在它内部,我有一个透明背景的flowlayout面板。当我滚动,会发生以下情况:在FlowLayoutPanel滚动期间,背景变形+闪烁

enter image description here

我也看到一些闪烁。我尝试过所有的双缓冲​​业务,但它不起作用。

有什么建议吗?

回答

10

是的,这是行不通的。以下是一些可以稍微改进的类:

using System; 
using System.Windows.Forms; 

class MyFlowLayoutPanel : FlowLayoutPanel { 
    public MyFlowLayoutPanel() { 
     this.DoubleBuffered = true; 
    } 
    protected override void OnScroll(ScrollEventArgs se) { 
     this.Invalidate(); 
     base.OnScroll(se); 
    } 
} 

将它从工具箱的顶部编译并放到表单上。但是它却无法解决根本问题,即“拖动时显示窗口内容”选项。这是一个系统选项,它将在更高版本的Windows中打开。当它打开时,Windows本身会滚动面板的内容,然后要求应用程序绘制滚动显示的部分。 OnScroll方法会覆盖该方法,确保重新整个窗口以保留背景图像。最终结果并不美观,你会看到图像在做“pogo”,在滚动的同时上下跳动。

唯一的解决方法是关闭系统选项。这不是一个实际的解决方案,用户喜欢这个选项,它会影响每个程序,而不仅仅是你的程序。如果你不能与pogo一起生活,那么你将不得不放弃透明度。

3

我很高兴地向大家汇报汉斯和互联网(只是学习WPF .... pfffft),在这里是错误的。

问题出在WM_HSCROLL和WM_VSCROLL事件上。通过一些试验和错误,我发现,如果我足够快地拖动滚动条,我就能够将背景的鬼副本移到实际的背景上,而背景却是我想要的背景。所以无论在可滚动控件内部发生什么,Windows 都是能够跟上,并且一些不同步重绘是导致剪切的原因。

那么你如何解决这个问题?

  1. 将您的可滚动控件设置为DoubleBuffered。

  2. 捕获WM_HSCROLL/WM_VSCROLL消息。无效。将“do_not_paint”标志设置为true。调用base.WndProc()。将“do_not_paint”标志设置为false。更新。

  3. 捕获WM_PAINT和相关消息。如果“do_not_paint”标志为false,则只调用base.WndProc()。

这样做是允许的滚动控制做任何布局计算和重新定位滚动条,它需要做,但不会让它重新绘制任何会触发剪切作用。

15

这是为我工作。

public class CustomFlowLayoutPanel : FlowLayoutPanel 
{ 
    public CustomFlowLayoutPanel() 
     : base() 
    { 
     this.SetStyle(ControlStyles.UserPaint, true); 
     this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
     this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
    } 

    protected override void OnScroll(ScrollEventArgs se) 
    { 
     this.Invalidate(); 

     base.OnScroll(se); 
    } 
    protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle |= 0x02000000; // WS_CLIPCHILDREN 
      return cp; 
     } 
    } 
} 
+1

我做到了这一点,它确实工作正常,但我也重新调整了重新调整大小,因为由于某种原因,它本身并不是很聪明。 – 2013-02-15 16:14:13

+0

太棒了,适合我。你能详细说明这个'CreateParams'实际上在做什么,你究竟是怎么发现这个的?你自己发现了吗? – 2014-02-12 14:21:50

+0

你是我的英雄! – 2014-10-25 00:48:40

1

这有点晚了...但是如果你弄乱了Color.Transparent,这件事就会发生。检查您的FlowLayoutPanel是否具有透明背景。如果是这样,请尝试改变它。

2

我将Application.DoEvents()添加到FlowPanel amd的Scroll事件中,该事件阻止了我正在获取的FlowPanel子控件的模糊。

+0

这是有史以来最简单最简单的解决方案。谢谢! – 2017-07-12 21:19:34