XP: Weird Set/ReleaseCapture causing WM_PAINT/ERASE_BACKGRND, somehow interfering with some XOR lasso logic
-
Wednesday, May 30, 2012 2:06 AM
I have an app that draws an XOR selection lasso. The logic is very sound. XP is throwing a wrench into the mix today...
For some reason whenever SetCapture or ReleaseCapture is called, it causes the capturing/releasing window to be sent a WM_PAINT event where the update region is for some reason the entire window. WM_ERASEBKGRND gets sent too. Strange thing is the background doesn't seem to actually get erased!!
Manually filling the update region with the background brush for WM_ERASEBKGRND does the trick, however it causes a considerable refresh effect over the window since there are a lot of children windows which must then be updated.
I don't understand how this sequence of events is even possible. Because a full erase should cause all of the child windows (one per entry in a colour palette) to refresh but it doesn't.
It seems like a really nasty hook is installed, or some kind of weird pattern specific to XP is in play. Any ideas?
Dunno why Microsoft stuck the underscore in my screen name. It won't wash out. I apologize, but I only post here in times of severe desperation :( Anyone else find the line/paragraph spacing in these forums very difficult to read?
All Replies
-
Wednesday, May 30, 2012 3:19 PM
Though I can't answer as to why XP is repainting the capturing window on set and then again on release (FOR NO REASON!) ... I wonder how many of the replies in these forums are people answering their own questions ... a problem in the painting logic was the capturing control is a group box, which apparently doesn't actually do anything for it's erase phase, as it's more or less an overlay, so the erase->refresh logic was begrudgingly moved up to the parent window's message procedure.
The control is still presumably repainted for no reason top to bottom including all of its many children, but to the end user its probably not noticed since the painting was complete unnecessary in the first place! Both times!!
Dunno why Microsoft stuck the underscore in my screen name. It won't wash out. I apologize, but I only post here in times of severe desperation :( Anyone else find the line/paragraph spacing in these forums very difficult to read?
-
Thursday, May 31, 2012 3:29 AMModerator
Hi Mick,
Welcome, actually, based on this description it is hard to show one image of your question and the issue. So could you please try to share some code snippet or some screenshots that can help us to know what it happens?
Regards to your first post, "WM_ERASEBKGRND gets sent too. Strange thing is the background doesn't seem to actually get erased. " You should know the WM_ERASEBKGRND and the WM_PAINT which one is sent first.
When the WM_PAINT is not caused by InvalidateRect, it is caused by resizing or moving, system will sent the WM_ERASEBKGND message first, then send the WM_PAINT. If we handle the WM_ERASEBKGND message and it returns FALSE, the BeginPaint marks pt.fErase to TRUE, else it is FALSE.
Others, when the WM_PAINT is caused by InvalidateRect, system sends the WM_PAINT first. If the bErase in InvalidateRect is TRUE, BeginPaint method can get the pending update region, and send one WM_ERASEBKGND message to window. It this message returns FALSE, BeginPaint marks pt.fErase to TRUE, else it is FLASE. The pt.fErase is TRUE means application should handle the background, however it is no necessary, pt.fErase is just one flag.
So how do you handle these messages actually? What is the order and the specific code?
Sincerely,
Bob Bao [MSFT]
MSDN Community Support | Feedback to us
-
Thursday, May 31, 2012 4:03 AM
I appreciate your concern Bob,
----
I don't think code or an image would help a whole lot. There is a group box over a solid dialog background. The box has coloured squares arranged in a grid with space between. And a text like selection lasso selects ranges of the boxes like text. There is a hidden control that covers everything, that is transparent, that draws the lasso with XOR rop like the focus rectangle you see when you use tab to move around UI elements.
Whenever an WM_ERASEBKGND message is received the transparent control is invalidated. It gets drawn by a WM_DRAWITEM notification.
----
The current implementation is a little naive in that it assumes if the control is erased, it will be erased entirely. Otherwise it seems sound.
The controls are part of a dialog. So to the best of my knowledge, there is no way to trap the WM_PAINT message using the normal dialog "window" proc arrangement.
The problem (in this case) seems to stem from knowing whether or not the background is truly erased -- because of the XOR rop, if you can't assume erasure, then you risk XOR'ing over the un-erased background and inadvertently erasing the XOR (if you understand how that works) and getting the XOR reversed at the same time.
Unfortunately, I can get things to work, but there are at least 2 (probably 3) scenarios where Windows behaves differently. Depending on what kind of theme / "period" you are in. Anyway, I went back and tried the fix with Windows 7 and got undesirable results. So I've taken the knuckle headed approach of using GetWindowTheme()==0 as an indicator of where to put the erase logic. If 0 the XOR is reset when the parent of the group control is erased, otherwise the reset is triggered in the child's erase handler... I shortly tried things with the XP style theme (I normally use the Classic-pre-XP theme with XP) before trying things out on 7, and that lead me to believe that probably that will be a 3rd scenario...
All of this is obviously not future proof. Probably Direct3D will be used ultimately anyway. But it all seems to hang on somehow determining when the background behind the selection area is truly erased or not. My guess this is why XOR seems to have gone out of fashion. In this case however it looks nice, and there are too many moving parts to disturb.
PS: This may be the first time anyone has ever replied to anything I've ever posted in these forums. I am not sure.
EDITED: I had meant to say, that I think some of the problem my lie in the underlying implementation of the group STATIC control in these different scenarios. I made it "transparent" to try to tighten the realm of possibilities, but that did not seem to help. I suspect in most cases it is effectively transparent, but in others it may not be. Spy++ had the box returning fErase==true even though there was obviously no erasing happening. I mean; if you are transparent, you can be erased but not erased at the same time, if you think about it too hard.
WM_PAINT was being received before WM_ERASEBACKGRND btw, but that was just in the original problem case. Other cases may be different. Unfortunately a non heuristical approach has yet to occur to me. I may as well add that the effect is really sophisticated in terms of how focus is managed mainly; it has been vetted in many different scenarios in other words. And so I would not doubt the implementation beyond the erase cue as described.
Dunno why Microsoft stuck the underscore in my screen name. It won't wash out. I apologize, but I only post here in times of severe desperation :( Anyone else find the line/paragraph spacing in these forums very difficult to read?
- Edited by Mick P. _ Thursday, May 31, 2012 4:17 AM
-
Tuesday, June 05, 2012 3:48 AMPostMessage a WM_PAINT manually might be one choice
Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
Regards,
Jacky Wu
Microsoft Online Community Support


