Date: | February 19, 2007 / year-entry #59 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20070219-00/?p=27963 |
Comments: | 28 |
Summary: | 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... |
Poor misunderstood
This is the first in a series on
What
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:
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(hwndA); // locks window A LockWindowUpdate(hwndB); // also locks window B LockWindowUpdate(NULL); // ???
What does that third call to void BeginOperationA() { LockWindowUpdate(hwndA); ... } void EndOperationA() { ... LockWindowUpdate(NULL); } void BeginOperationB() { LockWindowUpdate(hwndB); ... } void EndOperationB() { ... LockWindowUpdate(NULL); }
Imagine that the
Now suppose operation B finishes while a drag/drop is
still in progress.
Then
If // 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 |
Comments (28)
Comments are closed. |
This post might not be needed now had someone at Microsoft updated the LockWindowUpdate docs a year and a half ago when you wrote about it.
If they’d only added something to the effect of “this function should only to be called to disable drawing in the window beneath the cursor during a drag and drop operation?”
Raymond, thank you a lot for starting that subject. I can admit that I tried to use that function once and I didn’t get the results I expected. I almost jumped from joy as I saw what you write about. I can’t wait for the rest of the series. (Yes I now it sounds geeeeky, but I can’t help it).
"all attempt to draw into it or its children fail"
Does it realy fail or is it just deferred.
Fail would mean to me I get an error or something similiar.
Well, we will see.
Before I’ve read your other posts about what it really is useful for, it struck me that it would be simpler if you introduced transactions here? (e.g., with help of the new Kernel Transaction Manager).
So, applications can do whatever they want with the window and some poor component should take care of merging everything together when it is commited :)
Would at least be interesting to see if a prototype based on this works. Or perhaps this isn’t necessary anymore now with the Desktop Window Manager?
Look forward to the rest of this serie :)
Can I call LockWindowUpdate() in .NET?
"Can I call LockWindowUpdate() in .NET?"
Yes, you can use P/Invoke.
http://pinvoke.net/default.aspx/user32.LockWindowUpdate
> 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 this is only one per-desktop, how would different applications synchronize the use of this call? Or is it one per thread?
An error message for drawing "failure" would be really amazingly silly.
Everything from "you’re drawing into the hiden part of a window that’s a little bit off the edge of the monitor" to "you’re drawing into the hiden part of a window that’s partly covered by another window" would technically result in no change to the display, but it’s not an error condition worth handling – and there’s no need for every application to duplicate code that ought to be (and in fact actually is) handled efficiently and intelligently by the operating system.
Instead, the Win32 system just tells your application what to repaint and when to repaint it, and thus ensures that updates occur when necessary and appropriate.
Nothing is "deferred" – after calling LockWindowUpdate(), any drawing oeprations on the affected window fail, get ignored, result in no change, and are not queued up for later execution. And this is perfectly sensible and reasonable behaviour.
>I thought I already discussed this, on the tension between “descriptive” and “prescriptive” documentation. -Raymond
I don’t remember that one but will look for it. At this point I don’t see how anything could possibly apply though. This was a function that, according to you, was added for and had one and only one purpose/use, yet the documentation never mentions it. Is there no wonder it’s misunderstood and misused? How does one use a function as intended when its one intended use isn’t documented?
Wouldn’t it have been possible to give LockWindowUpdate sort of a per-thread or per-process affinity? So it can only lock or unlock its own windows, and if some program does something wrong, it is this process that has to pay? Otherwise any program can sabotage others on the same desktop, right? But most probably this is again a backwards compatibility issue, I guess, though I don’t remember if LWU was available on Win16. I am curious as to the rest of this series on LWU…
When I tried using this function on windows 95 for some reason the desktop icons would refresh themselves. It was bizarre. Needless to say I stopped using it.
Ahem:
RCW 9A.04.020
Purposes — Principles of construction.
(1) The general purposes of the provisions governing the definition of offenses are:
(a) To forbid and prevent conduct that inflicts or threatens substantial harm to individual or public interests;
(b) To safeguard conduct that is without culpability from condemnation as criminal;
(c) To give fair warning of the nature of the conduct declared to constitute an offense;
(d) To differentiate on reasonable grounds between serious and minor offenses, and to prescribe proportionate penalties for each.
(2) The provisions of this title shall be construed according to the fair import of their terms but when the language is susceptible of differing constructions it shall be interpreted to further the general purposes stated in this title.
Revised Washington Code — RCW section 9A.04.020
This is why I use WM_SETREDRAW liberally, and LockWindowUpdate never. But I’m interested in seeing the rest of the series to work out what it’s actually for :)
‘Do I have to write “of course there may be exceptions but I’m just making a point” after every sentence?’
That’s why Scott Adams (of Dilbert fame) uses the abbreviation BOCTAOE in his blog a lot. (‘But Of Course There Are Obvious Exceptions’)
I made a test case of a windows app that called WM_SETREDRAW FALSE on itself for 5 seconds, and tried dragging across it.
It’s pretty funny. The WM_MOUSEMOVEs get sent to the window UNDER the now-undrawable window and scribbling on the undrawable (and undraggable) window. The crap stays there when the window comes back to life, of course–WM_SETREDRAW does no invalidation.
Peter: I can’t seriously believe you thought that was actually helpful in any way…
I’ll generously assume some criminal quoted that construction thing of a law I’ve never heard of and that such an action disproves Raymond’s assertion.
In the humanities one has to be precise as one deal with very complex systems – groups of people. People think in schemas. So we are already predisposed to generalise anything into an absolute rule.
I find the more deterministic arts and sciences, like API programming (not just of OSs but all from MS), so imprecide. I can’t be bothered to write code anymore as it always involves setting up experiments to get the real rules of many things.
So my take is if one talks in absolutes then one should be nitpitted as one has shown a lack of rigerous thinking. Though if one does this in social situations then one is thought wierd.
Raymond, can you link to the function’s documentation on MSDN the first time you mention a function? Pretty please with a seared salmon cube on top?
Like http://msdn2.microsoft.com/en-us/library/ms534869.aspx (at least I think that’s the right link to it)
Maybe it’s intended for window moving.
Users can move exactly one window at a time. (One mouse = one window)
So if you don’t want to bother the user with updating window while moving it, the easiest way is to put LockWindowUpdate at the start and end of the moving process.
You don’t need to program some "background buffer". All is done by OS itself.
Thanks Anony Moose
Fully agreed.
A LockWindowUpdate unaware, non native english nitpicker now would state that it probaply would be clearer to write:
"When a window is locked, all attempt to draw into it or its children result in no effect" BOCTAOE
Just good I’m not such one, instead silently wait for the next post on this promising topic.
Ha, here it is:
http://msdn2.microsoft.com/en-us/library/ms534872.aspx
So it helps to protect your window from being overdrawn but still being able to draw your valuable content to the DC with help of DCX_LOCKWINDOWUPDATE when moving/resizing.
It’s funny.
It seems that OS uses it very often, right in front of our eyes, but developers don’t now how to use it, nor they even know what it is good for.
For temporarily drawing into somebody else’s window.
(This is regarding Raymond’s comment "And the criminal code doesn’t tell you the intent of a law.")
Looking at the little bits of paper in my little home office here, I can come up with the following alternate phrases for everyone to use:
"Telephones don’t tell you why to call people"
"Menus don’t tell you why you should eat"
"Printer manuals don’t tell you why you should print"
"The internet doesn’t tell you why to surf"
Food wrappers, on the other hand, are a fount of suggestions — this marshamllow bag has a pretty tasty looking ‘crispy rice bars’ recipe.
:-) of course.
(personally I’d love for all API documentation to give ‘serving suggestions’)
"When a window is locked, all attempt to draw into it or its children result in no effect".
I don’t think that generalization is correct. It does have an effect, just not the same as if the window were not locked–it caches the bounds of any updates and forces a WM_PAINT of that boundary when the window becomes not locked. (for clarity, if no updates occured, no WM_PAINT results).
> 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.
Does MSDN agree?
Pavel S., thank you for posting this link:
http://msdn2.microsoft.com/en-us/library/ms534872.aspx
* While a window update lock is set, the system
* creates an accumulated bounding rectangle for
***** each locked window.
* When the lock is cleared, the system uses
* this bounding rectangle to set the update
* region for the window and its child windows
There are also other situations where multiple somethings can be moved in one mouse dragging operation. You can’t hold the control key and select multiple ordinary windows, but you can select multiple icons on the desktop to move their locations, or you can select multiple icons for files in Windows Explorer and drag them to another Windows Explorer (to move or copy) or to a desktop icon (to print or unpack or whatever).
Norman: But it also says this, in the documentation for LockWindowUpdate itself (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_4i5h.asp):
> Return Values
> If the function succeeds, the return value is nonzero.
>
> If the function fails, the return value is zero, indicating that an error
> occurred or another window was already locked.
I think Raymond is correct. The way to read that "each locked window" bit is to remember the fact that you lock the window you pass in *and its children*.
Um, not dragging.
PingBack from http://entrian.com/blog/setting-a-visual-studio-breakpoint-on-a-win32-api-function-in-user32dll/