3
votes

It seems that my window is flickering whenever I move and window and resize at the same time. This usually occurs when sizing is done from the left side of the window.

Why does this flickering happen? In other words, what is the OS doing when you reposition a window?

Note: I do not experience flickering when resizing from the right side which means the window is not necessarily moving its origin X and Y.

2
The reason is because you're moving the entire window. Windows is going to now redraw everything at that specific position. Shrinking from the right side only makes it repaint its borders. The client area does not need repainting as it's just cropped. Stretching from the right requires that whatever controls wasn't painted will now be drawn as well as the client area. Moving a window requires repainting every single component and the client area as well as its borders.Brandon
@CantChooseUsernames I am trying to connect what you said to this SWP_NOCOPYBITS. But I thought it just copies the bits over.Mathew Kurian
What OS are you using? Windows XP with themes enabled (i.e. by default) has unavoidable flicker. All other versions of Windows except Vista are OK. I haven't tried Vista.arx

2 Answers

5
votes

Resizing a window under Windows involves several messages sent between the OS and the window's handler (the lpfnWndProc member of WNDCLASSEX structure used to register the window's class). You can discover them by yourself using some message monitoring tool. Spy++ that comes with Visual Studio is one such tool.

One interesting message is WM_NCCALCSIZE: this message, called during window resizing, can generate two rectangles (when WVR_VALIDRECTS flag is set): source and target specifying what content of the old window's client area can be "reused" at the new window's position. By default it's assumed that the top-left corner is a pivot:

  • resizing the left or top border causes the old window's content to get copied to preserve the pivot;
  • resizing the right ot bottom border copies nothing because the top-left corner of the window did not move.

This default copying can cause flicker, if it does not correspond to the way you position visuals during repaint. For example, everything that is displayed relative to the right or bottom border will be misplaced after resize from the left or top border: these objects will get moved unnecessarily leaving strange mix of old and new things after such resize, because only non-copied pixels will be repainted. If you try to cure the mess with InvalidateRect during, say, WM_SIZE you will get the flicker (the time interval where things are misplaced is very short but it still exists).

The easiest way to disable this behavior is by setting the CS_HREDRAW and CS_VREDRAW Class Styles for your window.

0
votes

A 2018 update.

The WM_NCCALCSIZE WVR_VALIDRECTS trick is still a good way from preventing Windows XP/Vista/7 SetWindowPos from doing a needless BitBlt that causes the flickering.

However, Microsoft did it again and on Windows 8/10, the DWM window manager adds another layer of BitBlt on top of the legacy SetWindowPos BitBlt which can cause the same problem and is harder to work around.

For an explanation of why the unwanted BitBlt causes flickering, as well as sample code of the WM_NCCALCSIZE WVR_VALIDRECTS trick and some code ideas for how to prevent Windows 8/10 Aero from doing the same, please see:

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