USER & GDI Compatibility in Windows Vista (part 1)
So mostly I blog about WPF, which is where I’ve spent most of my time the last few years. But I also work on USER and GDI, along with many full-time USER & GDI'ers, and wanted to spend a little time talking about compatibility. We put a lot of effort into compatibility, and Windows Vista runs most software written for Windows XP without a hitch. But absolute 100% compatibility isn’t possible (especially in a beta!), and we’d like your help and feedback. Does your application work on Windows Vista? Can you change it to work? Do you need us to make changes? How do you think we’re doing on compatibility?
We recently published https://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnlong/html/AppComp.asp which describes common compatibility hotspots in Windows Vista. Good document, but it doesn’t talk a lot about USER and GDI (yet – I’m working on it <g>). So in the meantime, thought I’d write a few things about USER and GDI-specific issues.
Part 1 -- Painting issues
As part of the Desktop Window Manager work, we’ve made subtle but important changes to the way applications paint to the screen. Prior to Windows Vista, hwnds painted directly to the screen, which had certain benefits but really limited how Windows could display and manage top-level windows. In Windows Vista, all top-level windows are rendered to an offscreen bitmap (similar to WS_EX_LAYERED), and the desktop window manager combines the images together to draw the desktop.
Things to pay attention to when testing:
- Black areas around tool tips, pop-up menus, balloons, splash screens, etc. -- This can happen when the application has not painted the entire hwnd, usually because that application assumed that the pixels in the background windows are good enough. This is an area we’re actively doing work on, so don’t overly optimize based on current bits but please give us the feedback.
- Flashes of black – A related issue happens when applications do painting that's not part of a WM_PAINT. USER detects the application is drawing and redraws the desktop, but the application may not have finished drawing the hwnd when that happens, and the result is the backing bitmap contains uninitialized pixels (black). Again, we’re actively working here so please give us feedback on where you think we need to improve.
- Glass disabled for application -- this can happen when an application draws to the non-client area of the window (the title bar)
- Rubber bands, custom shadows, and other special effects – these are often done using GetDC(NULL), however reading and writing to GetDC(NULL) tends to be problematic when applications are backed by a bitmap rather than drawing straight to the screen. Reading and writing to the screen is significantly slower than Windows XP. Also, not all GDI rasterops are supported (but we do support XOR).
- Improved Far East fonts – Windows Vista has made numerous changes to the Chinese, Japanese, and Korean fonts to make them more readable; one of the side effects is that text can layout slightly differently in these new fonts as characters may have different widths. Consider testing how your text lays out on the screen and on the printer. Also consider testing places where Far East languages can be mixed with Latin character sets (e.g. English).
A lot of this is DWM-related, Greg Schector's blog is a great place for background info on DWM.
Next up: performance differences
Comments
- Anonymous
April 04, 2006
My app gets all messed up when I run it in 192 dpi mode. It seems as if the mouse messages dont have the proper transforms applied to them (or perhaps .PointToScreen/Client are the problem). Should I be worried about this or is this a known issue that will be addressed? - Anonymous
April 04, 2006
The comment has been removed - Anonymous
April 05, 2006
From Nick Kramer. - Anonymous
April 05, 2006
Based on what you say, I'm looking forward to running the Lotus Notes client on Vista. Ought to be fun to see what that quirky beast looks like :-) - Anonymous
April 05, 2006
In:
http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
Raymond Chen had an example where he detected if the program was running on a remote desktop so he could turn off double buffering. I asked if there was a way to detect something like this in general given an HDC. Since there was no response my guess is that there isn't.
Now, it's pretty clear that Vista will double buffer GDI apps for you. My assumption is that you can turn this on or off (dynamically and at runtime). In any event, in the WM_PAINT message how can you detect if Windows is double buffering for you so apps can disable their own double buffering code to save time blitting and space from a large bitmap allocated?
Ideally what I would want you to tell me is that whoever wrote this was smart enough to recognize this usage pattern so it occurs automatically but my app uses a DIB (not a DIBSECTION) so it can access the pixels so I doubt this case is covered. - Anonymous
April 05, 2006
You can detect if the DWM is on (and thus your application is double buffer) by calling DwmIsCompositionEnabled(), and listening for WM_DWMCOMPOSITIONCHANGED messages to see if the DWM is turned on/off while your application is running.
I don't believe we have any logic to detect applications doing double buffering and bypass that, every application does it a little differently... - Anonymous
April 06, 2006
"Since there was no response my guess is that there isn't."
Or I didn't understand the question and didn't feel like pursuing it. WindowFromDC will tell you if you have the DC for a window but that's still the wrong question. Even if you decide you have a memory DC, double-buffering is wrong if the result is going to be BLTed to a remote DC when you're done. - Anonymous
April 06, 2006
Read the linked page for clues to how Apple solved these same problems some years ago. They require developer intervention, but that may be the only way. - Anonymous
April 06, 2006
Hmmm. That link showed up in a pretty obscure place. Here it is again:
http://developer.apple.com/documentation/Performance/Conceptual/Drawing/Articles/CarbonDrawing.html - Anonymous
April 10, 2006
kokorozashi -- thanks for the suggestion! - Anonymous
April 19, 2006
I just remembered another point about the way Apple did this. They made it possible for an
application to determine whether windows are automagically double-buffered, and they made
it possible to do this on systems which never automagically double-buffer windows. To put
it in more specific terms, Mac OS 9 does not automagically double-buffer windows, but Mac
OS X does, yet a single app may run on either system and perform an identical test at runtime
to determine whether it should do its own double-buffering. This would make it easier and safer
for existing apps to avoid triple-buffering on Vista but still avoid flicker on XP. To make
this possible in an elegant way, don't add a function to Vista. Find some mechanism which
already exists in XP (are there any HWND extended style bits left?) and describe the code
a developer could write to determine that some existing bit is clear or at least determine
that the bit does not exist to be tested. Then, in Vista, you'd define the bit and set it,
so the same code would not only find the bit but see that it is set. Defining a bit like
this decouples the test from the version of the operating system, which is advantageous for
a number of reasons. - Anonymous
April 24, 2006
This content will make it into the master compatibility document in the next month or so, but in the... - Anonymous
May 28, 2006
The comment has been removed