During FlowLayoutPanel scrolling, background disto

2019-01-25 07:48发布

问题:

I have a windows form application that has a background. Within it, I have a flowlayoutpanel with a transparent background. When I scroll, the following happens:

I also see some flickering. I've tried all the doublebuffered business, and it doesn't work.

Any suggestions?

回答1:

Yeah, that doesn't work. Here's a class that improves it somewhat:

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

Compile and drop it from the top of the toolbox onto your form. It however cannot fix the fundamental problem, the "Show window content while dragging" option. That's a system option, it will be turned on for later versions of Windows. When it is on, Windows itselfs scrolls the content of the panel, then asks the app to draw the part that was revealed by the scroll. The OnScroll method overrides that, ensuring that the entire window is repainted to keep the background image in place. The end-result is not pretty, you'll see the image doing the "pogo", jumping up and down while scrolling.

The only fix for this is turning the system option off. That's not a practical fix, users like the option and it affects every program, not just yours. If you can't live with the pogo then you'll have to give up on the transparency.



回答2:

this is what worked for me.

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


回答3:

I am very pleased to report that Hans, and the internet at large (just learn WPF....pfffft), is wrong here.

The problem is in the WM_HSCROLL and WM_VSCROLL events. Through some trial and error, I found that, if I dragged the scroll bar fast enough, I was able to move a ghost copy of my background over the actual background which was fxied how I wanted it. So whatever is happening inside the scrollable control, Windows is able to keep up and some out of sync redraw is what's causing the shearing.

So how do you solve this problem?

  1. Set your scrollable control to DoubleBuffered.

  2. Catch the WM_HSCROLL/WM_VSCROLL messages. Invalidate. Set the "do_not_paint" flag to true. Call the base.WndProc(). Set the "do_not_paint" flag to false. Update.

  3. Catch the WM_PAINT and related messages. Only call base.WndProc() if the "do_not_paint" flag is false.

What this does is allow the scrollable control to do whatever layout calculations and scrollbar repositioning it needs to do but doesn't let it redraw anything that would trigger the shearing effect.



回答4:

I added Application.DoEvents() to the Scroll event of the FlowPanel amd that stopped the blurring of the FlowPanel child controls that I was getting.



回答5:

It´s a little bit late ... but this things happen if you mess with Color.Transparent. Check if your FlowLayoutPanel has Transparent Background. If so, try to change that.