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

Posted

技术标签:

【中文标题】在 FlowLayoutPanel 滚动期间,背景扭曲 + 闪烁【英文标题】:During FlowLayoutPanel scrolling, background distorts + flickers 【发布时间】:2011-03-21 10:34:31 【问题描述】:

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

我还看到一些闪烁。双缓冲业务我都试过了,还是不行。

有什么建议吗?

【问题讨论】:

【参考方案1】:

这对我有用。

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;
        
    

【讨论】:

我这样做了,它确实工作正常,但我也让它在调整大小时重新绘制,因为出于某种原因,它自己做它不是很聪明。 太好了,对我有用。你能否详细说明这个CreateParams 到底在做什么,你到底是怎么找到这个的?你自己发现了吗?【参考方案2】:

是的,这行不通。这是一个稍微改进它的类:

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】:

我很高兴地报告 Hans 和整个互联网(只要学习 WPF....pfffft)在这里是错误的。

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

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

    将可滚动控件设置为 DoubleBuffered。

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

    捕获 WM_PAINT 和相关消息。仅当“do_not_paint”标志为 false 时才调用 base.WndProc()。

这样做是允许可滚动控件执行它需要执行的任何布局计算和滚动条重新定位,但不会让它重绘任何会触发剪切效果的内容。

【讨论】:

【参考方案4】:

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

【讨论】:

这是有史以来最简单、最简单的解决方案。谢谢! Application.DoEvents 可能会中断您的程序逻辑,因此不应该如此轻易地使用它。相反,解决真正的问题! 是的,我不会使用 Application.DoEvents。当您确定有很多项目时,它可能会弄乱 flowlayoutpanel 项目。【参考方案5】:

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

【讨论】:

以上是关于在 FlowLayoutPanel 滚动期间,背景扭曲 + 闪烁的主要内容,如果未能解决你的问题,请参考以下文章

C#winform 怎么设置自动竖直滚动条

SLES12 vim - 背景更改滚动+复制粘贴问题

带有很多控件的假滚动容器

停靠更改时,UserControl 未在 FlowLayoutPanel 中呈现

动态生成PictureBox控件,涉及:PictureBox控件和flowLayoutPanel面板

FlowLayoutPanel 添加到列?