Flicker-free expansion (resize) of a window to the left

前端 未结 1 1095
眼角桃花
眼角桃花 2021-01-15 01:54

Say you have a form that you can expand to the left to show additional controls:

Collapsed:

Expanded:

相关标签:
1条回答
  • 2021-01-15 02:54

    I can provide some insight about why you see ghost images of the other half of your UI and possibly a way to stop it. The ghost image indicates that someone is copying your client area pixels (and copying them to the wrong place, always flush-left in your window) before you have a chance to redraw them with the correct pixels.

    There are likely two different, overlapping sources of these ghost pixels.

    The first layer applies to all Windows OSes and comes from a BitBlt inside SetWindowPos. You can get rid of that BitBlt in several ways. You can create your own custom implementation of WM_NCCALCSIZE to tell Windows to blit nothing (or to blit one pixel on top of itself), or alternately you can intercept WM_WINDOWPOSCHANGING (first passing it onto DefWindowProc) and set WINDOWPOS.flags |= SWP_NOCOPYBITS, which disables the BitBlt inside the internal call to SetWindowPos() that Windows makes during window resizing. This has the same eventual effect of skipping the BitBlt.

    However, Windows 8/10 aero adds another, more troublesome layer. Apps now draw into an offscreen buffer which is then composited by the new, evil DWM.exe window manager. And it turns out DWM.exe will sometimes do its own BitBlt type operation on top of the one already done by the legacy XP/Vista/7 code. And stopping DWM from doing its blit is much harder; so far I have not seen any complete solutions.

    For sample code that will break through the XP/Vista/7 layer and at least improve the performance of the 8/10 layer, please see:

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

    Since you have multiple child windows, the situation is even a little more complicated. The BitBlt type operations I mentioned above happen on your whole top-level window as a whole (they treat the window as one set of pixels regardless of how many windows are underneath, and regardless of CLIPCHILDREN). But you need to have windows move atomically so that on the next redraw they are all positioned correctly. You may find BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos useful for that (but only go there if the above tricks do not work).

    0 讨论(0)
提交回复
热议问题