Solved

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

Posted on 2002-07-23
6
1,322 Views
Last Modified: 2013-11-20
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
Comment
Question by:nicolet
  • 2
  • 2
6 Comments
 
LVL 9

Accepted Solution

by:
BeyondWu earned 200 total points
Comment Utility
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
 

Author Comment

by:nicolet
Comment Utility
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
 

Author Comment

by:nicolet
Comment Utility
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
 
LVL 9

Expert Comment

by:BeyondWu
Comment Utility
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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now