Windows ConfidentialThe Case of the Disappearing Cursor

Raymond Chen

You may have noticed that when you press the PrtSc key to take a screenshot, the cursor blinks briefly. Believe it or not, it actually does this for the same reason that the Windows XP fade-out shutdown screen does not include translucent windows.

These translucent windows, known as layered windows, are not normally included by the BitBlt function when reading pixels from the screen. In order to get them, you have to pass the CAPTUREBLT flag. When you do, you may also notice that the mouse cursor blinks. So why is that?

Once upon a time, the only graphical object that floated "above" the rest of the objects on your screen was the mouse cursor. Originally, the system supported only monochrome mouse cursors. These cursors were supported either in software or, if you happened to have an awesome video card, in hardware.

When you use a video card-supported cursor, the Graphics Device Interface (GDI) gives the video card a bitmap and a mask and says, "OK, this is the mouse cursor. Overlay this on the screen at the coordinates I specify." When the user moves the mouse, the GDI sends the video card updated coordinates, and the video card does the hard work of moving the pixels around the screen.

On the other hand, when you use a software-supported cursor, then the GDI is responsible for saving the pixels under the cursor before drawing it into the frame buffer. The procedure works in the following way: when the user moves the mouse, the GDI manually restores the original pixels, saves all of the pixels under the cursor's new position, and then it draws the cursor at that new position.

When a hardware cursor is employed, the pixels of the mouse cursor do not actually exist in the frame buffer because the hardware is responsible for performing the overlay. Consequently, the BitBlt function is able to just copy pixels from the frame buffer without fear of picking up pixels from the mouse cursor by mistake since those pixels don't exist in the frame buffer to begin with.

Conversely, if a software cursor is being used, then the GDI must remove the mouse cursor from the screen before performing a BitBlt from the screen if the region being copied overlaps the mouse cursor.

When animated cursors are employed, hardware cursors just don't quite cut the mustard, since hardware cursors don't animate. Therefore, animated cursors are implemented in software.

OK, great. But what does this have to do with CAPTUREBLT? Hang on, I'm getting there.

In Windows 2000, the composition mechanism that was used for software cursors was generalized so applications could also take advantage of it. These pseudo-cursors ultimately became known as layered windows. Like software cursors, layered windows don't show up when you do a BitBlt from the screen since they do not really exist in the usual sense. The pixels from the cursor and layered windows are composited onto the screen at the last moment.

But what if you want to capture the pixels of a layered window via BitBlt? That's where the new CAPTUREBLT flag comes into play. This captures the pixels after the composition engine has had its say. Since the code that generates the Windows XP dimmed shutdown screen doesn't pass the CAPTUREBLT, layered windows don't appear.

That still doesn't seem to explain why the cursor flickers, though. Actually, it does. The mouse cursor is just another composition object and therefore would be captured by the CAPTUREBLT flag. To prevent this from happening during a screen capture, the composition engine has to hide the cursor, do the CAPTUREBLT, and then re-show the cursor.

By exposing the Windows 2000 composition engine to applications, cursors have lost their special status. We've come full circle. It's now just like the good old days, back when all you had was a frame buffer and a software cursor.

Raymond Chen's Web site, The Old New Thing, and identically titled book (Addison-Wesley, 2007) deal with Windows history, Win32 programming, and misreading newspaper headlines.