Capturing Windows Regardless of Their Z-Order

Introduction

This article demonstrates how to capture top-level windows with the WS_VISIBLE style, regardless of their z-order.

Functionality Included

  • Capture all the screen content to a BMP file.
  • Capture the foreground window content to a BMP file.
  • Capture the covered window content to a BMP file.

All functionality is implemented inside the CaptureEx class and, in addition to capturing screen content, one can find other useful functionality of the class, such as:

  • Creating (saving) a BMP file from raw bits.
  • Converting any input HBITMAP into 24-bit raw bits.
  • Stretching (zoom in/out) BMP raw bits to a given window handle.

About the Project

Capturing window content can be done easily by using the ::BitBlt(..) from the screen DC; however, this kind of implementation forces you to make sure that the window you want to capture is on top of the screen. In this project, to capture all the screen (Desktop), this technique is useful. Because it's not good for capturing covered windows, I capture windows with the ::PrintWindow(..) API.

The project is a MFC-dialog based application, built with VC6. However, as mentioned above, all the implementations are inside the CaptureEx class, so actually MFC is being used just as a wrapper for the GUI; the CaptureEx functionality is implemented with the Win32 API. In that way, Win32 applications can also benefit from the class.

How It Works

When the application starts running, it uses ::EnumWindows(..) to build a list of all top/visible windows; each valid window for capturing is added to the list. Clicking "Refresh Windows List" will update the windows list.

Once you have all the windows in the list, you can select a window from the list (using the mouse/arrow keys); each selected window will be captured and displayed on the dialog. The capture is made without changing the window's Z-order.

You can change the preview slider to zoom in/out the captured window image; clicking "Show actual size" will display the captured window image at its real size.

To save a particular captured window to a BMP file, press the "Save window to Bmp" button.

All captured windows will be saved at their real size, no matter how the preview is set.

Note: Capturing minimized windows (Iconic) will only generate the caption image of the window. Here is a sample of Iconic window capture:

The CaptureEx Class

Useful functions of the CaptureEx class are shown in this code snippet:

class CaptureEx
{
   :
   public:
   void SaveBmpToFile(LPTSTR szFileName, int W,int H,
                      int Bpp, int* lpBits);
   void Get24BitBmp ( const int &nWidth,const int &nHeight,
                      const HBITMAP &hBitmap, BYTE *lpDesBits);
   void CaptureDesktop (double fPreviewRatio,
                        LPTSTR lpszFileName,
                        BOOL bSaveToFile);
   void StretchDIBitsToHwnd( HWND hWnd, double fRatio,
                             int Width, int Height,int Bpp,
                             BYTE *lpBits);
   BOOL CaptureWindow( HWND hWndSrc, double fPreviewRatio,
                       LPTSTR lpszFileName,BOOL bSaveToFile);
   :
   :
};

Known Issue

During the development of the application, I ran into a problem with capturing IE windows; sometimes, part of the image goes black. I assume it's due to the way IE windows repaint themselves. At the moment, the solution I came up with is to capture each window a couple of times and get the correct image by using image filtering.



Downloads