在FlowLayoutPanel滚动期间,背景扭曲+闪烁

16

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

输入图像描述

同时我还看到一些闪烁。我尝试了所有双缓冲业务,但都没用。

有什么建议吗?

6个回答

25

这是对我有效的方法。

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
我已经完成了这个任务,它可以正常工作,但是我还让它在调整大小时重新绘制,因为由于某种原因它自己并不很聪明地处理这个问题。 - Camilo Martin
很好,适合我。你能详细说明一下这个 CreateParams 实际上是做什么的吗?你是怎么找到它的?是自己发现的吗? - Mike de Klerk

13

是的,那样行不通。这里提供一个类可以稍微改进一下:

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方法覆盖了该操作,确保重新绘制整个窗口以保持背景图像不变。最终结果看起来不太美观,你会看到图像在滚动时“跳跃”或“弹跳”。

唯一的解决办法是关闭系统选项。这不是一个实际的解决办法,用户喜欢这个选项,它会影响每个程序,而不仅仅是你的程序。如果你不能忍受这种“跳跃”效果,那么你就必须放弃透明度。


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()。
这样做可以允许可滚动控件进行任何布局计算和滚动条重新定位,但不会让它重新绘制任何会触发图像扭曲效果的东西。

2

我在FlowPanel的滚动事件中添加了Application.DoEvents(),这样就可以避免FlowPanel子控件模糊的问题。


这是有史以来最简单和最简单的解决方案。谢谢! - Topher Birth
1
Application.DoEvents 可能会中断您的程序逻辑,因此不应轻易使用。相反,应解决真正的问题! - tmighty
是的,我不会使用Application.DoEvents。当您有很多项时,它可能会破坏flowlayoutpanel项目的顺序。 - Eldhose

2
这有点晚了...但如果你使用了Color.Transparent,这种情况就会发生。检查一下你的FlowLayoutPanel是否有透明背景。如果有,尝试更改一下。

0

尝试使用扩展窗口样式

 class MyFlowLayoutPanel : FlowLayoutPanel
{
    protected override CreateParams CreateParams
    {
        get
        {
            var cp = base.CreateParams;
            cp.ExStyle |=0x2000000 | 0x02000000;
            return cp;
        }
    }
    public MyFlowLayoutPanel()
    {
        this.DoubleBuffered = true;
    }
    protected override void OnScroll(ScrollEventArgs se)
    {
        this.Invalidate();
        base.OnScroll(se);
    }
}

1
目前你的回答不够清晰,请[编辑]以添加更多细节,帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接