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 http://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 (13)

  1. Martin says:

    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?

  2. nkramer says:

    Might have something to do with PointToScreen/Client, anything dealing with screen accordance tends to be problematic to translate from the real dpi to what the application expects to see.  One of the upcoming compatibility posts is going to be about high dpi, if you send me an e-mail I’ll get you that post a few days earlier and see if it sheds any light on your issue.  Thanks.

  3. Joe Reader says:

    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 🙂

  4. asdf says:

    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.

  5. nkramer says:

    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…

  6. oldnewthing says:

    "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.

  7. kokorozashi says:

    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.

  8. kokorozashi says:

    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

  9. nkramer says:

    kokorozashi — thanks for the suggestion!

  10. kokorozashi says:

    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.

  11. This content will make it into the master compatibility document in the next month or so, but in the…

  12. jeff says:

    <<Rubber bands, custom shadows, and other special effects – these are often done using GetDC(NULL),…

    …(but we do support XOR). >>

    Nick,

    I just did a little testing of my GDI based app on Vista Beta 2, and I have an XOR’d rubberband that’s drawn on the desktop DC for a certain UI effect. It’s very slow as you say, but it also does not draw correctly (leaves traces).

    However, I was very pleased to see that the performance of good ol’ GDI BitBlit with a DIBSECTION seems as fast as it was on XP. Is it mapped somehow to DirectX?

    –jeff