What’s the story behind the WM_SYNCPAINT message?


Danail wants to know the story behind the WM_SYNC­PAINT message.

The documentation pretty much tells the story. When a window has been hidden, shown, moved or sized, the system may determine that it needs to send a WM_SYNC­PAINT message to the windows of other threads. This message must be passed to Def­Window­Proc, which will send the WM_NCPAINT and WM_ERASE­BKGND messages to the window as necessary.

When you call the Set­Window­Pos function, the window manager updates the window size, position, whatever, and then it goes around repainting the windows that were affected by the operation. By default, the Set­Window­Pos function does a quick-repaint of the windows before returning. After the function returns, the normal WM_PAINT message does the real work of painting the window. The quick-repaint is done so that there is immediate feedback that the window did change its size, position, whatever.

This quick-repaint is done by sending a WM_NCPAINT and WM_ERASE­BKGND message to the windows that were affected by the Set­Window­Pos operation. This normally happens without incident, but if one of the windows affected by the Set­Window­Pos operation belongs to another thread, the window manager needs to get into the context of that other thread to finish the job. That's where WM_SYNC­PAINT comes in. The WM_SYNC­PAINT message means, "Hey, I was going around quick-painting a bunch of windows, but I couldn't quick-paint you (or any other windows on your thread) because I was on the wrong thread. Could you finish quick-painting yourself (and all the other windows that need quick-painting)? Thanks."

Another way of looking at this is that it is a way for the window manager to teleport itself into another thread so it can finish its work. "Lah di dah, quick-painting all the windows, oh crap, I can't quick-paint that window because it's on the wrong thread. Let me inject myself into that other process [trivial, since I'm the window manager, I'M IN YR PROCESS REEDING YR MSGS], and now I can send a message to myself [WM_SYNCPAINT], and when that other copy of me receives it, he'll finish where I left off."

If you don't like any of this teleportation or multiple-copies-of-yourself imagery, you can say that the WM_SYNC­PAINT message means, "Quick-paint this window as part of a quick-paint operation begun on another thread."

If you don't want this quick-paint to take place, you can follow the instructions in the documentation and pass the SWP_DEFER­ERASE flag to suppress the WM_SYNC­PAINT message.

Comments (11)
  1. Cesar says:

    Let's see if I understand: the moral of the story is "WM_SYNC­PAINT is an internal message, just treat it like any other message you do not know about (that is, let it slide through the default case in your switch, which will do nothing more than calling DefWindowProc) and everything will work fine".

  2. @Cesar: I was thinking similarly.  In fact, why did they document WM_SYNCPAINT in the first place if it's only used internally?  I'm trying to think of a case where I'd actually need to know about it.  The only thing I can think of is debugging (e.g. sniffing messages with Microsoft Spy++ – you might wonder what those undocumented messages are).  If the documentation did not document WM_SYNCPAINT and instead documented that all unknown messages should go to the default window procedure then all would be fine (in theory, anyway!).

  3. Random User 4592752 says:

    I'm going to hazard a guess that "internal" messages such as this got documented as a goofy result of a certain court order.

  4. Cesar says:

    @JamesJohnston: "all unknown messages should go to the default window procedure"

    Forgive me if I am wrong (more of a Unix programmer, so I might get some Windows-specific things wrong), but I believe it is deeper than "all unknown messages"; it is "all messages your window procedure does not care about" (which includes unknown/undocumented messages, but also known and documented messages which are not relevant to your window). That is, treat only the messages which matter to you, pass the rest to DefWindowProc and let it return the applicable "this message makes no sense" error codes.

  5. Joshua says:

    @Cesar: If you read Raymond's blog, you'll see the real reason for passing all unknown is so new messages added in a future version of Windows get their default behavior.

  6. 640k says:

    the real reason for passing all unknown is so new messages added in a future version of Windows get their default behavior.

    aka unknown unknowns messages.

  7. henke37 says:

    Wouldn't it be known unknowns if you were expecting new windows versions to add messages, but didn't know what those would be?

  8. Crescens2k says:

    But since they haven't been added, so you just don't know what the messages are, wouldn't that make them unknown known unknowns?

  9. Engywuck says:

    of course I know that this is a remnant of ancient times when memory was scarce and furry things from alpha centauri were still furry things from alpha centauri, but…

    …would that method with the "Paint Thyself" message still get implemented today or would it be easier/better to give every windo a 2D-plane it can paint what it wants on and then use some z-Koordinate (plus perhaps Alpha blending) to generate a composite of all those windows for the Desktop user?

  10. ChristW says:

    @Engywuck:

    IIRC that's the way OS-X does it… every window is drawing to a surface that's a texture for the GPU to composite on-screen.

  11. Medinoc says:

    That's also how Windows does it since Vista (by default).

Comments are closed.