对LockWindowUpdate可怜的误解。
这是关于LockWindowUpdate系列的第一篇。LockWindowUpdate的行为,它是用于做什么的,以及(可能更重要的是)它不是用于做什么。
LockWindowUpdate
做的事情其实很简单。当一个窗口被“锁定”,所有向它及其子窗口的绘制都会失败。取代绘制操作的是,窗口管理器记住了应用程序试图在窗口的哪一部分中进行绘制。当窗口“解锁”后,这些区域被无效化,使得应用程序得到一个WM_PAINT消息,从而重新恢复了屏幕内容与应用程序认为应当在屏幕上显示的内容之间的同步。
大家已经在CS_SAVEBITS看到了“记录在情形X有效时,应用程序试图做的绘制,并在情形X不再有效时做无效处理”这样的行为。在这种意义上,LockWindowUpdate做了同样的簿记的工作。在你用一个CS_SAVEBITS窗口覆盖锁定的窗口时这个行为就会发生,只是这里不会保存什么数据。
在文档中明确的指出,同一时间只能有一个窗口被锁定。同时这也可以由函数原型暗示得出。如果两个窗口可以同时被锁定,将无法可靠的使用LockWindowUpdate。当你做下面的事情时将会怎样:
LockWindowUpdate(hwndA);
//
锁定窗口A
LockWindowUpdate(hwndB); // 将窗口B也锁定
LockWindowUpdate(NULL); // ???
LockWindowUpdate(hwndB); // 将窗口B也锁定
LockWindowUpdate(NULL); // ???
第三个对LockWindowUpdate的调用会做什么么?是把所有的窗口解锁?还是只解锁窗口A,或是只解锁窗口B?不论你如何回答,都不可能让下列的代码可靠的使用LockWindowUpdate:
void
BeginOperationA()
{
LockWindowUpdate(hwndA);
...
}
void EndOperationA()
{
...
LockWindowUpdate(NULL);
}
void BeginOperationB()
{
LockWindowUpdate(hwndB);
...
}
void EndOperationB()
{
...
LockWindowUpdate(NULL);
}
{
LockWindowUpdate(hwndA);
...
}
void EndOperationA()
{
...
LockWindowUpdate(NULL);
}
void BeginOperationB()
{
LockWindowUpdate(hwndB);
...
}
void EndOperationB()
{
...
LockWindowUpdate(NULL);
}
设想BeginOperation开始了由异步行为触发的某个操作。例如,假设操作绘制播放的反馈,因此开始于鼠标按下,并结束于鼠标释放。
现在假设仍在播放过程中时,操作B结束了。EndOperationB将会清理操作B,并调用LockWindowUpdate(NULL)。如果你假设这将解锁所有窗口,那么就会破坏了操作A,因为它预期hwndA仍被锁定。类似的,如果你提出应当只解锁hwndA,那么不只操作A被破坏了,操作B也会被破坏(因为尽管操作B已经完成,hwndB仍被锁定)。另一方面,如果你建议LockWIndowUpdate(NULL)应当解锁hwndB,那么请考虑一下操作A先于B完成的情况。
如果LockWindowUpdate同一时间能够锁定多于一个窗口,那么这个函数的原型就需要修改,以使得解锁的操作可以知道那一个窗口正在被解锁。有很多方法可以做到这一点,例如添加一个新的参数或是创建一个单独的函数。








但是这两个都不是实际的情况,LockWindowUpdate函数同一时间只锁定一个窗口。这样做的原因在了解了LockWindowUpdate是用来做什么的之后会更加清晰