Date: | January 24, 2011 / year-entry #17 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20110124-00/?p=11683 |
Comments: | 15 |
Summary: | If your window doesn't have a handler for the WM_SETREDRAW message, then DefWindowProc will give you a default implementation which suppresses WM_PAINT messages for your window when redraw is disabled, and re-enables WM_PAINT (and triggers a full repaint) when redraw is re-enabled. (This is internally accomplished by making the window pseudo-invisible, but that's an implementation... |
If your window doesn't have a handler for the Although the default implementation works fine for simple controls, more complex controls can do better, and in fact they should do better, because that's sort of the point of The intended use for disabling redraw on a window is in preparation for making large numbers of changes to the window, where you don't want to waste time updating the screen after each tiny little change. For example, if you're going to add a hundred items to a list box, you probably want to disable redraw while adding the items so you don't have to suffer through 100 screen refreshes when only one is enough. You've probably seen the programs that forget to suppress redraw when filling a large list box: The application freezes up except for a list box whose scroll bar starts out with a big thumb that slowly shrinks as the number of items increases. I say that this is sort of the point of For example, the list view control has a custom handler for Moral of the story: If you have a control that manages a large number of sub-items, you should have a custom Bonus chatter: Note that using |
Comments (15)
Comments are closed. |
I wish Visual Studio 2008 would use something like this for the toolbox sidebar which takes forever, as it adds each custom control one-by-one to the list while also repeatedly jumping between the topmost, bottommost and currently selected items in the list (for no apparent reason).
If you think vs2008 is slow, try vs2010.
Just don't use the designer and you'll be fine.
I almost never use it these days. I can do a smaller/faster/better job in code.
I wish Windows Live (DirectActiveX.NET just kidding) Mail programmers worked in the same company as Raymond Chen. Oops, they do. The damn thing doesn't know to use WM_SETREDRAW when deleting the mails from the list.
I wish the commenters would actually complain on the correct blog windowsteamblog.com/…/windowslive. Oops, that would mean they'd have to do something other than complain to someone who has nothing to do with said product. This means I have to read the damn comments that have nothing to do with the post.
@Alex I'm not really planning to do anything about it. It's a minor annoyance, honestly, and only an issue the first time I start up VS for the day. Still…I wish they had used something like WM_SETREDRAW. Just sayin'.
I've seen the angst over the 'wrong' use of LockWindowUpdate in favour of WM_SETREDRAW but my approach to reducing screen flicker in my Delphi Apps is rather empirical. In my tools box I have four possibilities – DoubleBuffered (writes the bitmap to a backing canvas before painting), BeginUpdate-EndUpdate (ListView, TreeView etc) LockWindowUpdate() and WM_SETREDRAW. I fiddle with each until I find a solution that looks nice. Invariably LockWindowUpdate looks best although I know its naughty. Why is it best?
@Alex Grigoriev;@Alex Grigoriev: I bet this is leftover from OE. I see exact same behaviour in winmail.
[It's not surprising that naughty gives the best results for the person being naughty. If your network card doesn't implement exponential backoff but instead always retransmits immediately, then you will win all collisions. If you steal from the store, you don't have to pay. If you grab all the crayons in art class, then you will have an easier time drawing your pictures. Of course, you also screw over everybody else. -Raymond]
Exponential backoff will most likely make collisions worse. Only random backoff will minimize collisions.
To draw flicker free in windows gdi you have to STEAL resources?
..and my real point is why should LockWindowUpdate() give a 'better' visual effect than WM_SETREDRAW?
talking about the listview control, its implementation of setredraw is very buggy. If I turn redraw off, then add/rearrange a lot of items, chances are that when redraw is re-enabled the control will not paint fully, not scroll correctly or both. The end result leaves much to be admired (especially in LVS_LIST) so usually I request a full redraw with Invalidate() after each WM_SETREDRAW(true)
Nikos, how is it buggy when it behaves exactly as documented?
This message can be useful if an application must add several items to a list box. The application can call this message with wParam set to FALSE, add the items, and then call the message again with wParam set to TRUE. Finally, the application can call RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN) to cause the list box to be repainted.
If you're trying to avoid flickering, I don't see how ShowWindow(SW_HIDE) would help. It sounds like you're suggesting that one should hide the control, perform updates, and show it again. That will definitely cause flickering!
The listview content is easily provoked to garbage when enabling gridlines and adding items.
Can you please clarify about WM_SETREDRAW message – does it allow nesting? I mean if you do SendMsg(WM_SETREDRAW, FALSE) twice, then SendMsg(WM_SETREDRAW, TRUE) twice, will it allow repainting only after second SendMsg(WM_SETREDRAW, TRUE)?
Also, from your post it is not very clear to me how should I implement WM_SETREDRAW. Are there any examples of how it could be done? For example, should I call default implementation? And what other messages should be handled in specific way while setredraw flag is set?