How to capture and print entire application window in MFC Doc/View

I have a SDI MFC application. How do I capture my entire application acreen and print the screen which includes title bar, 2 split window and status bar, and print the application window? Basically it is a snapshot of the applicaiton. I am using Doc/View.
nicoletAsked:
Who is Participating?
 
BeyondWuConnect With a Mentor Commented:
1.Get the HBITMAP of your whole window.
a. this function can get the bitmap of the whole window, no matter it's hide or show.
HBITMAP GetWndBmp(HWND hWnd/*your main window handle*/)
{
  if(hBitMap)
     DeleteObject(hBitMap);

  HDC hCatchDC = CreateCompatibleDC(NULL);
  HDC hTempDC = ::GetDC(NULL);
  RECT rect;
  ::GetWindowRect(hWnd, &rect);
  int nWidth = rect.right - rect.left;
  int nHeight = rect.bottom - rect.top;
  hBitMap = CreateCompatibleBitmap(hTempDC, nWidth, nHeight);
  HBITMAP oldbmp = (HBITMAP)SelectObject(hCatchDC, hBitMap);
  // let the window draw itself on my hCatchDC
  SendMessage(hWnd, WM_PRINT, (WPARAM)hCatchDC, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);

  ::ReleaseDC(NULL, hTempDC);

  SelectObject(hCatchDC, oldbmp);
  DeleteDC(hCatchDC);
  return hBitMap;
}

b. this function is simple and only get the visible windows.
HBITMAP GetWndBmp(HWND hWnd/*your main window handle*/)
{
  RECT rect;
  ::GetWindowRect(hWnd, &rect);
  int nWidth = rect.right - rect.left;
  int nHeight = rect.bottom - rect.top;

  HDC dc = GetWindowDC(hWnd);
  HDC hMemDC = CreateCompatibleDC(dc);
  HBITMAP hBitMap = CreateCompatibleBitmap(dc, nWidth, nHeight);
  HBITMAP oldbmp = (HBITMAP)SelectObject(hMemDC, hBitMap);

  BitBlt(hMemDC, 0, 0, nWidth, nHeight, dc, rect.left, rect.top, SRCCOPY);
     
  SelectObject(hMemDC, oldbmp);
  //DeleteObject(hBitMap);
  DeleteDC(hMemDC);
  ReleaseDC(hWnd, dc);
  return hBitMap;
}

2.Send to the printer
After get a HBITMAP of the window, it easy to send it to printer.
a. Get printer DC
  use CDC dcPrinter;
      CWinApp::CreatePrinterDC(dcPrinter)
or
  CDC dcPrinter;
  CPrintDialog pPD(FALSE);
  pPD.m_pd.Flags |= PD_RETURNDEFAULT;
  if(pPD.DoModal()==IDOK)
      dcPrinter.Attach(pPD.GetPrinterDC());

3. now, you can print it with startdoc/startpage/.. functions.

   DOCINFO docinfo;
   memset(&docinfo, 0, sizeof(docinfo));
   docinfo.cbSize = sizeof(docinfo);
   docinfo.lpszDocName = _T("print window test");

   if (dcPrinter.StartDoc(&docinfo) < 0)
   {
      MessageBox(_T("Printer wouldn't initalize"));
   }
   else
   {
      // start a page
      if (dcPrinter.StartPage() < 0)
      {
         MessageBox(_T("Could not start page"));
         dcPrinter.AbortDoc();
      }
      else
      {
         // actually do some printing
         // use StretchDIBits(hdcPrinter,0, 0, iWidth, ..
         // or use BitBlt(hdcPrinter, 0, 0, nWidth, ..
         // directly, because the Printer's DPI is higher
         // than Screen, so you maybe should resample the
         // hBitMap, so you'd better use StretchDIBits
 
         dcPrinter.EndPage();
         dcPrinter.EndDoc();
      }
   }
0
 
nicoletAuthor Commented:
In your answer to get
1.Get the HBITMAP of your whole window.
a. this function can get the bitmap of the whole window, no matter it's hide or show.

I have couple questions:
1. How did you get the hBitMap? before you check
if(hBitMap)
    DeleteObject(hBitMap);

2. When you do
// let the window draw itself on my hCatchDC
 SendMessage(hWnd, WM_PRINT, (WPARAM)hCatchDC, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);

Isn't that true that you assume ON_FILE_PRINT funciton has been implemented for printing the window in Doc/View platform? But how about the situation that application has not implemented the ON_FILE_PRINT, or the ON_FILE_PRINT will only print out parts of the document content?
In these cases how do you get your whole application window into the hCatchDC?


0
 
nicoletAuthor Commented:
Hi BeyondWu,

Also In your answer doing
       // actually do some printing
        // use StretchDIBits(hdcPrinter,0, 0, iWidth, ..
        // or use BitBlt(hdcPrinter, 0, 0, nWidth, ..
        // directly, because the Printer's DPI is higher
        // than Screen, so you maybe should resample the
        // hBitMap, so you'd better use StretchDIBits

StretchDIBits(hdcPrinter ...
or BitBlt(hdcPrinter..      

Who did you get this hdcPrinter? I suppose that hdcPrinter is different from dcPrinter.  
0
 
BeyondWuCommented:
It's only a clue and pseudocode for you, I have tested it, it only describes all necessary steps which you need.

1.Call if(hBitMap)DeleteObject(hBitMap); to avoid GDI leak, if you call the functions two or more times, it should delete the previous hbitmap.

2.Have nothing to do with ON_FILE_PRINT, have you ever study it in MSDN?

3.hdcPrinter = dcPrinter, my mistake.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.