On Win32, can I disable painting of a window for a period of time?
Asked Answered
H

3

7

Is there a function that will freeze window repainting for some time, while I do changes to the layout of my dialog?

Hillie answered 15/2, 2011 at 9:2 Comment(2)
I seriously doubt that you need to do this. Have you tried it and determined that you're actually getting a flood of WM_PAINT messages while you adjust your dialog's layout? Windows won't send a WM_PAINT message to the window procedure unless there are no other messages available for processing.Soppy
@Cody I'm sure that you know this, but Windows doesn't send WM_PAINT messages, rather it posts them. Quite an important distinction.Sthenic
S
16

If you find that you actually need to do this, you should send the window a WM_SETREDRAW message with the wParam set to FALSE. This indicates that the window should not be redrawn after its contents are changed.

When you want to re-enable drawing, send another WM_SETREDRAW message, this time with the wParam set to TRUE.

Sample code:

// Disable window updates
SendMessage(hWnd, WM_SETREDRAW, FALSE, 0);

// Perform your layout here
// ...

// Re-enable window updates
SendMessage(hWnd, WM_SETREDRAW, TRUE, 0);

For more information, Raymond Chen's blog article on the subject is a great read.

Soppy answered 15/2, 2011 at 9:14 Comment(10)
@Cody Gray, thanks, I need to do it because the application is skinned with SkinCrafter, and because we had problems with property pages I basically have a few picture buttons that act like tabs, and when user presses one of them I change to that tab by showing/hiding/moving all the widgets.Hillie
@satuon: Ugh. There's your problem. You're using hideous crap like skinning libraries. It shouldn't come as any surprise that things don't look and work exactly as expected.Soppy
@cody-gray Does this work for child windows, or do I need to send those messages to each of the child windows as well?Hillie
@satuon: Yeah, it works for child windows, as long as you send them the message. They repaint separately from their parent.Soppy
There was a minor problem when I added this code to my layout function, the taskbar icon didn't show up (I'm on on Windows 7), but I've fixed it by making sure the WM_SETREDRAW message isn't used the first time the function is called, which was before the dialog being shown for the first time.Hillie
@satuon: Yeah, if you never allow the window to get drawn, it won't ever get drawn on the taskbar either. Glad you found something that worked for you.Soppy
I don't think you do need to separately send WM_SETREDRAW to child windows. WM_SETREDRAW seems to work by subverting window visibility and child windows are always invisible when their parent is.Playwright
@Chris: That might be the case; I honestly don't know. But there are a couple of problems with that approach, both discussed in the article I linked to. First is that it's purely an implementation detail, and one that you shouldn't rely on. The behavior could theoretically change in a future version of Windows, as WM_SETREDRAW isn't documented as making the window pseudo-invisible and/or having any effect on child windows. Second, it assumes the default implementation, which is a mistake because you generally should provide a custom handler for WM_SETREDRAW that could work differently.Soppy
1. I think that the propagation of states, like shown & enabled states, AND SETREDRAW state, to child windows is always the expected. 2. You cannot implement SETREDRAW as effectively as the default implementation as the default implementation means that no call to GetDC will retrieve a display DC, which is a far stronger guarantee than a user implementation that can merely promise to not call GetDC.Playwright
In VS2019 debugging, leaving WM_SETREDRAW false can leave the app along with the NC controls unresponsive. So yeah, check all routines where it is required to be true again, or better, just add relevant conditions in WM_PAINT.Frivolity
S
3

You should do the repositioning in a single swoop; use BeginDeferWindowPos et al.

Suddenly answered 15/2, 2011 at 9:9 Comment(0)
S
1

The way Windows paints is that the system posts your window WM_PAINT messages instructing you to paint. You can elect to ignore these messages if you so wish, whilst you are modifying the layout, and then force a paint cycle once you have finished modifying the layout.

However, my experience of writing UI on Windows is that you usually don't need to take such steps. Since you are in charge of pumping your message queue, if the window is being refreshed whilst you are in the middle of modifying the layout, then you must have taken action that led to the message queue being pumped.

Put simply, stop pumping the queue whilst modifying the layout and your problems will vanish.

Sthenic answered 15/2, 2011 at 9:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.