关于c#:在FlowLayoutPanel滚动期间,背景失真+闪烁

During FlowLayoutPanel scrolling, background distorts + flickers

我有一个具有背景的Windows窗体应用程序。 在其中,我有一个透明背景的flowlayoutpanel。 当我滚动时,会发生以下情况:

enter image description here

我也看到一些闪烁。 我已经尝试了所有双缓冲业务,但是它不起作用。

有什么建议么?


这就是对我有用的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
2
3
4
5
6
7
8
9
10
11
12
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,则必须放弃透明度。


我将Application.DoEvents()添加到FlowPanel amd的Scroll事件中,该事件停止了我所获得的FlowPanel子控件的模糊。


我非常高兴地报告汉斯和整个互联网(只需学习WPF .... pfffft)在这里是错误的。

问题出在WM_HSCROLL和WM_VSCROLL事件中。经过反复试验,我发现,如果我足够快地拖动滚动条,就可以将背景的幻影副本移到实际背景上,而这正是我想要的。因此,无论可滚动控件内部发生了什么,Windows都能跟上,有些不同步的重绘是造成剪切的原因。

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

  • 将可滚动控件设置为DoubleBuffered。

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

  • 捕获WM_PAINT和相关消息。如果" do_not_paint"标志为false,则仅调用base.WndProc()。

  • 这样做是为了使可滚动控件进行布局计算和滚动条重新定位所需的操作,但不允许其重新绘制会触发剪切效果的任何内容。


    有点晚了...但是如果您对Color.Transparent感到困惑,就会发生这种情况。检查您的FlowLayoutPanel是否具有透明背景。如果是这样,请尝试更改它。