February 22nd, 2007

With what operations is LockWindowUpdate not meant to be used?

Okay, now that we know what operations LockWindowUpdate is meant to be used with, we can look at various ways people misuse the function for things unrelated to dragging. People see the “the window you lock won’t be able to redraw itself” behavior of LockWindowUpdate and use it as a sort of lazy version of the WM_SETREDRAW message. Though sending the WM_SETREDRAW message really isn’t that much harder than calling LockWindowUpdate. It’s twenty more characters of typing, half that if you use the SetWindowRedraw macro in <windowsx.h>.

Instead of LockWindowUpdate(hwnd)
Use SendMessage(hwnd, WM_SETREDRAW, FALSE, 0) or
SetWindowRedraw(hwnd, FALSE)
Instead of LockWindowUpdate(NULL)
Use SendMessage(hwnd, WM_SETREDRAW, TRUE, 0) or
SetWindowRedraw(hwnd, TRUE)

As we noted earlier, only one window in the system can be locked for update at a time. If your intention for calling LockWindowUpdate is merely to prevent a window from redrawing, say, because you’re updating it and don’t want the window continuously refreshing until your update is complete, then just disable redraw on that window. If you use LockWindowUpdate, you create a whole slew of subtle problems. First off, if some other program is misusing LockWindowUpdate in this same way, then one of you will lose. Whoever tries LockWindowUpdate first will get it, and the second program will fail. Now what do you do? Your window isn’t locked any more. Second, if you have locked your window for update and the user switches to another program and tries to drag an item (or even just tries to move the window!), that attempt to LockWindowUpdate will fail, and the user is now in the position where drag/drop has stopped working for some mysterious reason. And then, ten seconds later, it starts working again. “Stupid buggy Windows,” the user mutters. Conversely, if you decide to call LockWindowUpdate when a drag/drop or window-move operation is in progress, then your call will fail. This is just a specific example of the more general programming mistake of using global state to manage a local condition. When you want to disable redrawing in one of your windows, you don’t want this to affect other windows in the system; it’s a local condition. But you’re using a global state (the window locked for update) to keep track of it. I can already anticipate people saying, “Well, the window manager shouldn’t let somebody lock a window for update if they’re not doing a drag/drop operation.” But how does the window manager know? It knows what is happening, but it doesn’t know why. Is that program calling LockWindowUpdate because it’s too lazy to use the WM_SETREDRAW message? Or is it doing it in response to some user input that resulted in a drag/drop operation? Note that you can’t just say, “Well, the mouse button has to be down,” because the user might be performing a keyboard-based operation (such as resizing a window with the arrow keys) that has the moral equivalent of a drag/drop. Morality is hard enough to resolve as it is; expecting computers to be able to infer it is asking a bit much.

Next time, a final remark on LockWindowUpdate.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments

Discussion are closed.