How to fix the WPF form resize - controls lagging behind and black background?
Asked Answered
L

5

25

I have a very simple WPF window - the only thing in it is a right-aligned button. When I resize the window by dragging the left boundary, the button jumps around - a lot. Try it yourself, drag the left boundary back and forth.

Additionally, a black background becomes exposed temporarily during resizes.

In this question, I asked a similar question about Windows Forms. The only answer I got suggested that this is fixed in WPF, however, amazingly, not only is it not fixed, but WPF also adds a second visual bug - the temporary black background.

Here's what the control lag looks like; this occurs when I resize the window by its top border (recorded with a camera because screen-cap made it less obvious by making everything slow):

                                                  enter image description here

Example of the black border: this was captured while resizing the window; it's only like this for a split second but it's very noticeable:

                                      enter image description here

Am I doing something wrong? How can I have my controls stay visually in one place during resizes? How can I avoid the black border?

Note: the button ends up in the correct place eventually - it only jumps around briefly during the resize.

Lonne answered 5/9, 2009 at 9:54 Comment(2)
I just created a list of screenshots to demonstrate the idea.Farouche
It keeps me shocked. Microsoft create a wonderful technology to design beautiful user interfaces and introduced this awful visual bug.Farouche
G
12

This is complete working code based on Wieser Software Ltd's 2nd solution.

public partial class MainView : Window
{
    public MainView()
    {
        InitializeComponent();

        //ensure win32 handle is created
        var handle = new WindowInteropHelper(this).EnsureHandle();

        //set window background
        var result = SetClassLong(handle, GCL_HBRBACKGROUND, GetSysColorBrush(COLOR_WINDOW));
    }

    public static IntPtr SetClassLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
    {
        //check for x64
        if (IntPtr.Size > 4)
            return SetClassLongPtr64(hWnd, nIndex, dwNewLong);
        else
            return new IntPtr(SetClassLongPtr32(hWnd, nIndex, unchecked((uint)dwNewLong.ToInt32())));
    }

    private const int GCL_HBRBACKGROUND = -10;
    private const int COLOR_WINDOW = 5;

    [DllImport("user32.dll", EntryPoint = "SetClassLong")]
    public static extern uint SetClassLongPtr32(IntPtr hWnd, int nIndex, uint dwNewLong);

    [DllImport("user32.dll", EntryPoint = "SetClassLongPtr")]
    public static extern IntPtr SetClassLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

    [DllImport("user32.dll")]
    static extern IntPtr GetSysColorBrush(int nIndex);
}
Gissing answered 13/1, 2013 at 22:37 Comment(1)
This works to change the color of the black bit that shows. This can alleviate the issue to some extent, depending on the contents of the window. Of course for complex backgrounds (such as an image) the bit that shows is still noticeably wrong, since the underlying problem (control layout lag and having unpainted parts of the window briefly visible) still remains.Lonne
L
3

This doesn't seem to be possible in the current versions of WPF.

Lonne answered 3/10, 2009 at 17:44 Comment(0)
G
3

There are two solutions, described here: http://wieser-software.blogspot.co.uk/2012/06/wpf-window-rendering-woes.html

  1. Hook WndProc and handle WM_ERASEBKGND and draw the system WINDOW_COLOR on the background, or another color to suit your application theme.
  2. Call SetClassLong to set the Window Class Background Brush

    SetClassLong(Handle, GCL_HBRBACKGROUND, GetSysColorBrush(COLOR_WINDOW));

Gayelord answered 12/6, 2012 at 21:6 Comment(2)
This changes the color, indeed, so +1, but I'm trying to make the color not show through in the first place. I mean that's like the GDI days where everything repainted back-to-front. Can't it double-buffer?... :)Lonne
You could extend glass into the client area for a different effect, but it only works if aero is switched on.Gayelord
P
1

I believe that the temporary black background is a WPF issue related to the fact that WPF uses DirectX as rendering mechanism, and when you resize the windows it has to synchronize drawing with the windowing system. This may also explain why the button is misplaced in relation to the window while dragging the window border. Drawing the non-client area of the window is much slower than drawing what's inside the window, and if you move the mouse fast on a slow computer the discrepancies between the border end the internals of the window will probably be more noticeable.

Supposedly this only happens on Vista with Aero enabled, and it should have been fixed in Vista SP1. However, I just tested on SP2, and I did still see a little bit of black background, but only when Aero was enabled. My graphics card is pretty fast so it was hardly noticeable.

If my analysis is correct the only way you can fix your problem is to getter a faster graphics card or turn off Aero.

Phenetidine answered 8/9, 2009 at 8:9 Comment(2)
Thanks, your suggestion may make this less noticeable but can't eliminate it altogether. The problem is not how long it's visible for, but that it's visible at all... By the way, the problem is also present in Win7 RTM.Lonne
I see it with WPF4.0 and Win7 64bit SP1Figurant
N
0

Other answers have addressed how to fill in a different background colors to try and mitigate the effect of WPF slow drawing.

I can't offer any magic to speed up WPF but I can offer some insight about where the black is coming from.

The visual bug in your first screenshot is due to an extra layer of resize problem that Aero added, and there is a partial workaround.

I was fighting the issue of ugly live-resize in native Win32 apps and I created a roundup Question/Answer which brings together 10 years of posts on resize woes and offers some new insights (too long to paste the content here in this question). Please see:

How to smooth ugly jitter/flicker/jumping when resizing windows, especially dragging left/top border (Win 7-10; bg, bitblt and DWM)?

Niece answered 26/10, 2018 at 9:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.