Why does the MoveWindow function let you suppress repainting?


Commenter Phil Quirk asks via the suggestion box why the MoveWindow function lets you suppress repainting. "Shouldn't the OS be able to figure out if the window needs to be repainted?"

Indeed the window manager does do a very nice job of figuring it out if you pass bRepaint = TRUE, which is the expected value of the parameter. But if you think you're smarter than the window manager, then you can pass bRepaint = FALSE and tell the window manager, "Even though you think the window needs to be repainted, don't repaint it. Trust me on this."

Why would you try to outwit the window manager? Maybe you have special knowledge about how your application behaves. For example, you might exploit special properties about the source and destination coordinates and decide that certain portions of the window should not be redrawn but rather should be shared between the old and new locations, sort of like the advanced tricks you can play with the WM_NCCALCSIZE message. Or you might know that your program is going to invalidate the entire client rectangle soon anyway, so a repaint immediately after the move would just be a waste of time. The bRepaint parameter provides an escape hatch, a throwback to the days when the window manager let you do strange things because you might be doing them as part of a clever thing.

Mind you, these are pretty advanced concerns and most of the time you would be best off just passing bRepaint = TRUE and letting the window manager do its job of deciding what needs to be repainted.

Comments (8)
  1. Chuck Norris? says:

    The page from the link "why the MoveWindow function lets you suppress repainting" links to the blog of Zeke Odins-Lucas, which links to the Microspotting website, which has a recent(ish) interview with Raymond…

    http://www.microspotting.com/2009/01/raymond-chen

    which links back to this blog…

  2. Bob says:

    As a rule, you move windows in response to user input, otherwise you’re liable to move the window somewhere that will annoy the user.

    Therefore "I’m about to move a bunch of windows" counts as special knowledge of the fact that somehow you have a reason to do that and its what the user will want.

  3. Alexandre Grigoriev says:

    Bob,

    How about resizing of a form or a dialog, with automatic rearrangement of the controls?

  4. Dean Harding says:

    I think people forget that a "window" in Windows does not just mean top-level windows.

  5. Alexandre Grigoriev says:

    The "special knowledge" is not the point.

    If bRepaint is TRUE, WM_PAINT is *sent* immediately in the MoveWindow context, causing the window to repaint before the function returns, rather than "lazily" in the message loop.

    If you are moving or resizing  a lot of windows, you may not want them to repaint immediately.

  6. Leif Strand says:

    It is interesting to compare/contrast the classic Mac here.

    In the Macintosh Toolbox, the functionality of Win32’s MoveWindow is split between two routines, MoveWindow and SizeWindow.  Not coincidentally, SizeWindow has the exact same parameter ("fUpdate") with (almost) the exact same semantics:

    http://developer.apple.com/DOCUMENTATION/mac/Toolbox/Toolbox-251.html

    The difference is, on the Mac, the behavior is always "lazy".  At the same time, they neglected to include an ‘fUpdate’ parameter to MoveWindow:

    http://developer.apple.com/DOCUMENTATION/mac/Toolbox/Toolbox-246.html

    Indeed, since the Mac is always lazy, there is no need for an ‘fUpdate’ parameter in the "move a bunch of windows" scenario.  You just move the windows around with abandon, confident that you will be fed a stream of update events later (one per window — no redundant drawing will occur).

    Nonetheless, the Mac team felt the need to include ‘fUpdate’ with SizeWindow.  As Raymond alluded to, it probably has to do with coordinates.  Maybe I want the content to shift in response to the resize, in which case the default update region would be annoying.

    Going even deeper, I wonder if the reason that Windows is *not* lazy has to do with update events.  As I recall, Windows doesn’t have "update events" — there is WM_PAINT but it’s not quite the same thing.  On the Mac, update events are funny things which are handled specially by the Toolbox.  They aren’t even posted to the queue (otherwise you could get two redundant update events for the same window).  Maybe the Windows team decided that update events were an ugly/useless concept… but were thus forced to make MoveWindow redraw the window immediately when bRepaint=TRUE.

  7. streuth says:

    This one made me think a bit.

    I thought to myself…. I don’t think I’m using move window *anywhere*. SetWindowPos would be a preferable call to my way of thinking. So I did a grep on everything I do, and have written, for the word "MoveWindow".

    You must consider, that I cant remember why all the functions I have written exist!

    As it happens I have a prototype for "MoveWindow" that simply calls "SetWindowPos". Stranger still, my own prototype has a repaint parameter!!!!

    I’d say that I probably coded it, with the idea that I could move multiple windows as children (perhaps overlapping) and then repaint them all in one go on conclusion of the multiple move. My own "MoveWindow" appears to forego activation when called with repaint set to false. When set to true it also foregoes activation but forces both pane and frame painting.

    As it turns out, the only time I call "MoveWindow" with repaint set to false, is when I have a windows button control drawn on top of part of a windows edit control. In that instance it seems that I’m moving the window into position, showing it, and then zing to the fore.

    Who knows if it’s the right way to do it, but I’m fairly sure it works O.K.

    HTH

  8. Ulric says:

    it’s common.  Not the first case mentionned by Raymond (exploiting special knowledge), but the second.  Alexandre Grigoriev above is correct.

    it’s to avoid flicker and embarassing performance, when you move a bunch of child windows, for example when resizing a dialog, you can do a final InvalidateRect( hwnd, NULL ) at the end and get on repaint instead of a bunch of them.  

    now of course, there is DeferWindowPos, but that function probably came much later (was it even in Windows 3.x?) – and I think it is generally little known.

Comments are closed.