As I noted earlier, the intended purpose of
LockWindowUpdate
can be captured in one word: dragging.
The simplest case of LockWindowUpdate
is used by the window manager when you move or resize a window and "Show window contents while dragging" is disabled. When you start the move/size operation, the window manager locks the entire desktop so it can draw the dotted-rectangle feedback without risking interference from another window that happens to intersect the dotted-rectangle. When the move/size operation is complete, the desktop is unlocked, and the world returns to normal.
A common case where an application uses LockWindowUpdate
is if it wants to draw a custom image when offering drag feedback. In this case, the application locks its own window in order to draw the drag feedback. It then uses the DCX_LOCKWINDOWUPDATE
flag to get a DC that it can use to draw the desired feedback, and it doesn't have to worry about the window procedure or any other code in the application accidentally drawing to the feedback window and messing up the drag image. For example, if the application is displaying drag feedback on a list view, and some asynchronous event caused the list view contents to change (say, an item got added), and the drag image just happens to be where the new item is about to appear, you wouldn't want the normal redraw behavior of the listview to overpaint (or worse, merge with) the drag image.
A case where you would want to lock another application's window is if you are dragging an object across the screen. You might do this if you are a program like Spy that has an option to let the user select a window by dragging a "selection gadget" over it. Not only do you have to lock the window the use is selecting so that its own painting won't conflict with your "selection gadget", but also so that it doesn't conflict with the highlight effect you place around that window.
By now, you've probably noticed a common thread to all of these LockWindowUpdate
scenarios: They all involve dragging of some sort. Dragging a window caption to move it, dragging the edge of a window to resize it, dragging an item into a window, or dragging an item out of a window. This is not a coincidence. The LockWindowUpdate
function was designed with these drag scenarios in mind. Since dragging an item uses the mouse button, and there's only one mouse, you can't have multiple drag operations in progress at once, and therefore, there's no need to lock more than one window for update at a time. The function should perhaps more accurately have been named LockDragWindow
.
> there’s only one mouse, you can’t have multiple drag operations in progress at once
Not necessarily. There’s MultiPoint.
We use LockWindowUpdate for avoiding extensive redraw operations when reorganizing child windows/controls in an window. Without it you can see the windows changing position, with it you don’t and you just go from one layout to the new one without flickering.
Isn’t WM_SETREDRAW preferred for avoiding flicker in such cases?
Why do other windows flicker when I use LockWindowUpdate?
Awesome, things like this rock. I am finishing up my last 2 quarters getting a CS degree, but things like this will never be learned inside of a class room, and I am willing to bet that they would take a long time to learn on the job as well! (Especially judging from the goodly number of replies by people who don’t know what the function is for! :) )
Thanks for the knowledge transfer!
Can I vote for a:
#define LockWindowUpdate LockDragWindow
in the Platform SDK for the next Windows, along with an update to the exports in user32, (add the new name, plus a forwarder entry for the old name, so current programs keep working — the param could stay the same)? :-P
(Actually, that may be possible, but it’s likely a waste of time. Too bad…)
Perhaps it is to discourage you from using LockWindowUpdate?
> Why do other windows flicker when I use LockWindowUpdate?
Perhaps it is to discourage you from using LockWindowUpdate inappropriately?
DeferWindowPos is a little bit complicated to use when you have a lot of existing code based on the traditional way of positioning windows.
When building a window you can easily put everything at the right place to begin with and it does not have any visible or slow down effect.
It is more troublesome when you have to handle resizing and you have implemented very specific resizing policies based on WM_SIZE message.
Using LockWindowUpdate is much simpler for these cases without having to rewrite a lot of code.
Since LockWindowUpdate is for dragging, why does the MSDN page on it have no indication of that at all? The word ‘drag’ isn’t anywhere on the page.
Raymond,
Could you include a small code example that shows how LockWindowUpdate might be used in conjuctions with ImageList_DragShowNolock, ImageList_DragMove with the added complication of handing scrolling when dragging near the target window border. I’m sure the ordering is crucial (as it often is) but I just can’t seem to get it right without flicker and redraw artifacts. :(
Hi Raymond,
Your first poster queried the assumption about only one mouse, and you added that that assumption is in the win32 programming model. I don’t believe you have to preface everything you say with “In the win32 programming model” at all.
This does however raise an interesting discussion point. There _are_ more than one mouse present on some systems. Some games (kung-fu hustle, for example) encourages more than one mouse. Other applications might do the same.
How does win32 then cope with this? What other assumptions (aside from this one scenario) fails with more than one mouse present in the system? Maybe even more general than that, how does the win32 team go about keeping up with changing assumptions?
Regards,
Pieter
Can’t wait for the rest of this series!
First off, thank you for taking on LockWindowUpdate(). Learning about DeferWindowPos() was a very nice bonus!
That said, my first thought was "so this is why two mice aren’t supported". (meaning they both control the same cursor IIRC)
A couple of years ago, I had two computers on my desk. I operated my main computer with my left hand (I’m right handed btw) and the other with my right hand. The brain halves won’t allow this to work asynchronously (atleast mine won’t), but you can sort of fake it, and on larger monitors you should be able to shave off some time (move the closest mouse cursor).
I.e. it’s not entirely a bad idea… Specially not on three+ monitor systems… (granted, you never argued it was a bad idea, I’m just offering some input for future topics)
In case you don’t have a spare mouse on hand… there’s still only one cursor, and both mice would control it.
There’s an interesting program called GlovePIE somewhere out there which allows you to map keys, mouse buttons and movements, joystick axis and buttons, etc etc etc to each other. One of the interesting features is it can create additional fake mouse pointers which you can map to things. Of course the fake pointers don’t work 100% (I believe they only send fake window messages) but it’s still interesting to experiment with.
If you want it so bad just do:
#define LockDragWindow LockWindowUpdate
in your own code and let MS name things how they want to. :)
Um, not dragging.
kung-fu hustle?
There is only one pointing device in windows at a time. you have pen and a mouse, whoever moved last is the last mouse message, they are fighting for the same global pointer.
Games would use DirectInput
> Do I have to preface every sentence with “In the Win32 programming model
I thought MSR built this on top of Win32…
Anyway it is obvious that the API was designed years before anyone thought about multiple pointers.
LockWindowUpdate就是专门设计用于这些拖拽场景的。由于拖拽对象要用到鼠标按键,而只会有一个鼠标,故而同一时间不会有多个拖拽操作进行。因此,没有必要同时锁定多个窗口的更新。也许这个函数应当更准确的命名为LockDragWindow。