Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1550
  • Last Modified:

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.
0
nicolet
Asked:
nicolet
  • 2
  • 2
1 Solution
 
BeyondWuCommented:
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

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now