What does LockWindowUpdate do?

Raymond Chen

Raymond

Poor misunderstood LockWindowUpdate.

This is the first in a series on
LockWindowUpdate,
what it does, what it’s for and (perhaps most important) what it’s not for.

What LockWindowUpdate does is pretty simple.
When a window is locked,
all attempt to draw into it or its children fail.
Instead of drawing, the window manager remembers which parts of
the window the application tried to draw into, and when the
window is unlocked, those areas are invalidated so that the
application gets another WM_PAINT message,
thereby bringing the screen contents back in sync with what
the application believed to be on the screen.

This “keep track of what the application tried to draw
while Condition X was in effect, and invalidate it when
Condition X no longer hold” behavior you’ve seen already
in another guise:

CS_SAVEBITS
.
In this sense, LockWindowUpdate does the same bookkeeping
that would occur if you had covered the locked window with a
CS_SAVEBITS window, except that it doesn’t save any bits.

The documentation explicitly calls out that only one window
(per desktop, of course)
can be locked at a time, but this is implied by the function prototype.
If two windows could be locked at once, it would be impossible
to use LockWindowUpdate reliably.
What would happen if you did this:

LockWindowUpdate(hwndA); // locks window A
LockWindowUpdate(hwndB); // also locks window B
LockWindowUpdate(NULL); // ???

What does that third call to LockWindowUpdate do?
Does it unlock all the windows?
Or just window A?
Or just window B?
Whatever your answer, it would make it impossible for the following
code to use LockWindowUpdate reliably:

void BeginOperationA()
{
 LockWindowUpdate(hwndA);
 ...
}
void EndOperationA()
{
 ...
 LockWindowUpdate(NULL);
}
void BeginOperationB()
{
 LockWindowUpdate(hwndB);
 ...
}
void EndOperationB()
{
 ...
 LockWindowUpdate(NULL);
}

Imagine that the BeginOperation functions started
some operation that was triggered by asynchronous activity.
For example, suppose operation A is drawing drag/drop
feedback, so it begins when the mouse goes down and ends when
the mouse is released.

Now suppose operation B finishes while a drag/drop is
still in progress.
Then EndOperationB will clean up operation B
and call
LockWindowUpdate(NULL).
If you propose that that should unlock all windows,
then you’ve
just ruined operation A, which expects that hwndA
still be locked.
Similarly, if you argue that it should unlock
only hwndA, then only only is operation A ruined,
but so too is operation B (since hwndB is still
locked even though the operation is complete).
On the other hand, if you propose that LockWindowUpdate(NULL)
should unlock hwndB, then consider the case where
operation A completes first.

If LockWindowUpdate were able to lock more than one
window at a time, then the function prototype would have to have
been changed so that the unlock operation knows which window is
being unlocked.
There are many ways this could have been done.
For example, a new parameter could have been added
or a separate function created.

// Method A - new parameter
// fLock = TRUE to lock, FALSE to unlock
BOOL LockWindowUpdate(HWND hwnd, BOOL fLock);
// Method B - separate function
BOOL LockWindowUpdate(HWND hwnd);
BOOL UnlockWindowUpdate(HWND hwnd);

But neither of these is the case.
The LockWindowUpdate function locks only one window at a time.
And the reason for this will become more clear as we learn
what LockWindowUpdate is for.

Raymond Chen
Raymond Chen

Follow Raymond