?
Solved

How do i print a bitmap to my printer from my Formview

Posted on 2003-03-16
9
Medium Priority
?
436 Views
Last Modified: 2007-12-19
Hello, i have two big problems:
i'm using a derived formview class and i have lots of problems printing some basic stuff to paper.
I can print text easily, but the printing of bitmaps just never happens grrr whyyy?????
someone please help me on this.. it has destroyed my whole weekend now..
The other problem is i can't use the default print/print preview menu commands in my formviews. They are disabled.. Why?? And how do i enable them and get them to work?? thanks!

my code:

void CSD2View::OnPrint(CDC* pDC, CPrintInfo*)
{
      //The Following code scales the image based on printer resolution.
      pDC->SetMapMode(MM_ANISOTROPIC);
      pDC->SetWindowExt(m_pMemDC->GetDeviceCaps(LOGPIXELSX),m_pMemDC->GetDeviceCaps(LOGPIXELSY));
      pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX),pDC->GetDeviceCaps(LOGPIXELSY));
      //pDC->StretchBlt(0,0,m_rect.Width(),m_rect.Height(),m_pMemDC,0,0,m_rect.Width(),m_rect.Height(),SRCCOPY);
            CString test_address = "Romeinsestraat 810\r\nResearch park Haasrode\r\nB-3001 HEVERLEE\r\nBelgium";
            TEXTMETRIC tm;
            pDC->GetTextMetrics(&tm); //get the size of a text char.
            int YInterval = tm.tmHeight;
            CRect fig = CRect(50,250,600,1000);
            pDC->DrawText(test_address,fig,DT_LEFT);
            CBitmap bitmapResource;
            bitmapResource.LoadBitmap(MAKEINTRESOURCE(IDB_PRINTLOGO));
            BITMAP bmResource;
            bitmapResource.GetBitmap(&bmResource);
            
            CDC memClientDC;
            memClientDC.CreateCompatibleDC(pDC);
            CBitmap *pOldBitmapResource = (CBitmap *)memClientDC.SelectObject(bitmapResource);
            if (pOldBitmapResource == NULL)
            {
                  memClientDC.DeleteDC();
                  return ;
            }
            
            CDC memPrinterDC;
            memPrinterDC.CreateCompatibleDC(pDC);
            
            CBitmap bitmapPrinter;
            bitmapPrinter.CreateCompatibleBitmap(&memPrinterDC, bmResource.bmWidth, bmResource.bmHeight);
            CBitmap *pOldBitmapPrinter = (CBitmap *) memPrinterDC.SelectObject(bitmapPrinter);
            if (pOldBitmapPrinter == NULL)
            {
                  memClientDC.DeleteDC();
                  memPrinterDC.DeleteDC();
                  return ;
            }
            
            memPrinterDC.BitBlt(0,0,bmResource.bmWidth, bmResource.bmHeight, &memClientDC, 0,0, SRCCOPY);
            pDC->StretchBlt(0, 0, bmResource.bmWidth, bmResource.bmHeight, &memPrinterDC, 0, 0, bmResource.bmWidth, bmResource.bmHeight, SRCCOPY);
            
}

void CSD2View::OnBeginPrinting(CDC* pDC, CPrintInfo* /*pInfo*/)
{
      if (m_pMemDC->GetSafeHdc()) m_pMemDC->DeleteDC();
      m_pMemDC->CreateCompatibleDC(pDC);
      
      CClientDC dc(this);
      CRect rect;
      GetClientRect(rect);
      m_pMemDC->SetMapMode(MM_ANISOTROPIC);
      m_pMemDC->SetWindowExt(dc.GetDeviceCaps(LOGPIXELSX),dc.GetDeviceCaps(LOGPIXELSY));
      m_pMemDC->SetViewportExt(m_pMemDC->GetDeviceCaps(LOGPIXELSX),m_pMemDC->GetDeviceCaps(LOGPIXELSY));
      
      if (m_pBm->GetSafeHandle()) m_pBm->DeleteObject();
      m_pBm->CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());
      m_pMemDC->SelectObject(m_pBm);
      dc.DPtoLP(rect); //Convert to Logical Coordinates
      m_rect = rect;   //Save Logical Coordinates
      m_pMemDC->BitBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);
      //CFormView::OnBeginPrinting(pDC, pInfo);
}

For now i need to add this to get a printjob started (linked to a button)
void CSD2View::OnFilePrint()
{
      // get default print info
      CPrintInfo printInfo;
      //ADDED
      //printInfo.m_bPreview = TRUE;
      ASSERT(printInfo.m_pPD != NULL);    // must be set
      
      DoPreparePrinting(&printInfo);
      
      if (OnPreparePrinting(&printInfo))
      {
            // hDC must be set (did you remember to call DoPreparePrinting?)
            ASSERT(printInfo.m_pPD->m_pd.hDC != NULL);
            
            // gather file to print to if print-to-file selected
            CString strOutput;
            if (printInfo.m_pPD->m_pd.Flags & PD_PRINTTOFILE && !printInfo.m_bDocObject)
            {
                  // construct CFileDialog for browsing
                  CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT));
                  CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT));
                  CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER));
                  CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION));
                  CFileDialog dlg(FALSE, strDef, strPrintDef,
                        OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter);
                  dlg.m_ofn.lpstrTitle = strCaption;
                  
                  if (dlg.DoModal() != IDOK)
                        return;
                  
                  // set output device to resulting path name
                  strOutput = dlg.GetPathName();
            }
            
            // set up document info and start the document printing process
            CString strTitle;
            CDocument* pDoc = GetDocument();
            GetParentFrame()->GetWindowText(strTitle);
            if (strTitle.GetLength() > 31)
                  strTitle.ReleaseBuffer(31);
            DOCINFO docInfo;
            memset(&docInfo, 0, sizeof(DOCINFO));
            docInfo.cbSize = sizeof(DOCINFO);
            docInfo.lpszDocName = strTitle;
            CString strPortName;
            int nFormatID;
            if (strOutput.IsEmpty())
            {
                  docInfo.lpszOutput = NULL;
                  strPortName = printInfo.m_pPD->GetPortName();
                  nFormatID = AFX_IDS_PRINTONPORT;
            }
            else
            {
                  docInfo.lpszOutput = strOutput;
                  nFormatID = AFX_IDS_PRINTTOFILE;
            }
            
            // setup the printing DC
            CDC dcPrint;
            OnBeginPrinting(&dcPrint, &printInfo);
            dcPrint.Attach(printInfo.m_pPD->m_pd.hDC);  // attach printer dc
            dcPrint.m_bPrinting = TRUE;
            // disable main window while printing & init printing status dialog
            AfxGetMainWnd()->EnableWindow(FALSE);
            
            // start document printing process
            if (!printInfo.m_bDocObject && 
                  dcPrint.StartDoc(&docInfo) == SP_ERROR)
            {
                  // enable main window before proceeding
                  AfxGetMainWnd()->EnableWindow(TRUE);
                  
                  // cleanup and show error message
                  OnEndPrinting(&dcPrint, &printInfo);
                  dcPrint.Detach();   // will be cleaned up by CPrintInfo destructor
                  AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
                  return;
            }
            
            BOOL bError = FALSE;
            printInfo.m_nCurPage = 1;
            OnPrepareDC(&dcPrint, &printInfo);
            // set up drawing rect to entire page (in logical coordinates)
            printInfo.m_rectDraw.SetRect(0, 0,
                  dcPrint.GetDeviceCaps(HORZRES),
                  dcPrint.GetDeviceCaps(VERTRES));
            dcPrint.DPtoLP(&printInfo.m_rectDraw);
            // page successfully started, so now render the page
            OnPrint(&dcPrint, &printInfo);
            // cleanup document printing process
            dcPrint.EndDoc();
            AfxGetMainWnd()->EnableWindow();    // enable main window
            OnEndPrinting(&dcPrint, &printInfo);    // clean up after printing
            dcPrint.Detach();   // will be cleaned up by CPrintInfo destructor
      }
}
0
Comment
Question by:Joeriw
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
9 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 8150686
You are not checking the return from
       bitmapResource.LoadBitmap(MAKEINTRESOURCE(IDB_PRINTLOGO));

That's the first thing to try.  The next thing to try is to remove all scaling logic, in case it is flawed (I did not check it)
-- Dan


0
 

Author Comment

by:Joeriw
ID: 8153238
it returns fine, it also previews fine, it just doesnt print. Anyhow i already solved in a very 'long' way the bitmap painting to a printer, if someone can just help me now on enabling those print menu commands in the File menu for a CFormView (yes, i've read they arent implemented in the cformview), i'll be glad to donate him 200pts
0
 

Author Comment

by:Joeriw
ID: 8153311
ps for those with same bitmap problem goto http://www.codeproject.com/printing/printingtricksandtips.asp?target=ddbtodib for help
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 49

Expert Comment

by:DanRollins
ID: 8154271
There is good info and code here:
     http://codeguru.earthweb.com/printing/print_preview.shtml

I recall finding printing difficult at first.  What I did was disect the simplest print-capable CView -- the CEditView class.  I noticed the print-related functions that the AppWizard placed in the view code, and I single-stepped through that code that takes place during printing.  It's not tremendously complicated, but not simple either.  The view needs to cooperate with the frame in some parts of the process.

The problem with printing a CFormView revolves around the difficulty of prining each of its controls.  Some controls are built for on-screen display and "printing to paper" simply makes no sense.  For example, a ComboBox -- there is no place to print all of the items in the drop-down list.  Or a CListView -- some stuff may be below the bottom or off to the right of the on-screen rectangle.

The final solution is to *not* print the form itself, but to print the information that the user wants and needs, in a custom report format.  Drawing the contents of the form itself is normally a waste of time.

-- Dan
0
 

Author Comment

by:Joeriw
ID: 8154319
i know that, i override the OnDraw with an OnPrint anyway. All i need is to let the user print from the menubar. And preview from it too. I could consider using a separate ID_ instead of ID_FILE_PRINT and invoke the procedure in the same way as i did for the "Print" button.
I will read through your links in the morning. Thanks, i hope i can solve them now.
And indeed, i underestimated the printing part too :)
0
 

Author Comment

by:Joeriw
ID: 8234803
i had 2 real problems here:
the first one i found the solution to myself (see above) and the second one still noone was able to answer, and i meanwhile have found an answer for that one too. I'd like thus a refund so i can use it as an extra for my current difficult problem of printing from win98 to a laserjet ( http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_20567923.html )
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8234900
For info on how to get a refund, see:
    http://www.apollois.com/EE/Help/Closing_Questions.htm#AnsMyOwnQues
0
 

Author Comment

by:Joeriw
ID: 8234915
i know Dan, i had to add the comment before i could get the refund. I hope you agree with my decision. Next month i'll start working for a bigger company, i'll try to get a subscription then :)
0
 

Accepted Solution

by:
SpideyMod earned 0 total points
ID: 8238783
PAQ'd and all 200 points refunded.

SpideyMod
Community Support Moderator @Experts Exchange
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses

752 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