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):
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:
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.
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); }
This doesn't seem to be possible in the current versions of WPF.
There are two solutions, described here: http://wieser-software.blogspot.co.uk/2012/06/wpf-window-rendering-woes.html
Call SetClassLong to set the Window Class Background Brush
SetClassLong(Handle, GCL_HBRBACKGROUND, GetSysColorBrush(COLOR_WINDOW));
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With