Click here to Skip to main content
15,887,027 members
Articles / Programming Languages / C++
Article

Printing without the Document/View framework

Rate me:
Please Sign up or sign in to vote.
4.69/5 (41 votes)
29 May 2002CPOL1 min read 364.9K   130   85
Shows how to print without relying on the MFC Doc/View framework

Introduction

If you have a dialog based application and want to print, then you cannot take advantage of the Doc/View framework that MFC provides to do all the dirty work for you. The code presented below demonstrates the typical steps needed to:

  • prompt the user for the printing characteristics such as printer and paper size (via a call to CPrintDialog::DoModal)
  • Setup a printer DC and printing DOCINFO structure
  • Use callbacks to adjust settings such as start and end pages to print, or printing sizes
  • Print all pages to be printed
  • Cleanup

The callbacks

In order to keep the MFC Doc/View feel I recomend providing helper callback functions OnBeginPrinting, OnEndPrinting and OnPrint similar to the CView versions. A CDC and a CPrintInfo object is passed into each of these functions. You will have to provide these functions yourself. Typically you would undertake any initialisation neessary (such as creating GDI objects) in OnBeginPrinting. Your OnPrint function would be where you do the actual printing/drawing, and your OnEndPrinting function performs any cleanup necessary (such as deleting GDI objects created in OnBeginPrinting). You can call these functions whatever you want - I've used these names to be consistant with the CView names, and they are only used to show where the various initialisation/printing/cleanup code should be inserted by you.

Typical implementations would look like:

void OnBeginPrinting(CDC *pDC, CPrintInfo* pInfo)
{
    // maybe pre cache some pens or brushes, or modify the
    // properties of the DC
}

void OnPrint(CDC *pDC, CPrintInfo* pInfo)
{
    // Do your drawing/printing exactly as you would in a
    // CView::OnDraw function. The CPrintInfo structure
    // will give you the bounds and the current page number
}

void OnEndPrinting(CDC *pDC, CPrintInfo* pInfo)
{
    // Clean up pens or brushes, or restore the DC
}

The Printing code

void CMyDialog::Print() 
{
    CDC dc;
    CPrintDialog printDlg(FALSE);

    if (printDlg.DoModal() == IDCANCEL)     // Get printer settings from user
        return;

    dc.Attach(printDlg.GetPrinterDC());     // Get and attach a printer DC
    dc.m_bPrinting = TRUE;

    CString strTitle;                       // Get the application title
    strTitle.LoadString(AFX_IDS_APP_TITLE);

    DOCINFO di;                             // Initialise print document details
    ::ZeroMemory (&di, sizeof (DOCINFO));
    di.cbSize = sizeof (DOCINFO);
    di.lpszDocName = strTitle;

    BOOL bPrintingOK = dc.StartDoc(&di);    // Begin a new print job

    // Get the printing extents and store in the m_rectDraw field of a 
    // CPrintInfo object
    CPrintInfo Info;
    Info.m_rectDraw.SetRect(0,0, 
                            dc.GetDeviceCaps(HORZRES), 
                            dc.GetDeviceCaps(VERTRES));

    OnBeginPrinting(&dc, &Info);            // Call your "Init printing" function
    for (UINT page = Info.GetMinPage(); 
         page <= Info.GetMaxPage() && bPrintingOK; 
         page++)
    {
        dc.StartPage();                     // begin new page
        Info.m_nCurPage = page;
        OnPrint(&dc, &Info);                // Call your "Print page" function
        bPrintingOK = (dc.EndPage() > 0);   // end page
    }
    OnEndPrinting(&dc, &Info);              // Call your "Clean up" function

    if (bPrintingOK)
        dc.EndDoc();                        // end a print job
    else
        dc.AbortDoc();                      // abort job.

    dc.DeleteDC();                          // delete the printer DC
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder CodeProject
Canada Canada
Chris Maunder is the co-founder of CodeProject and ContentLab.com, and has been a prominent figure in the software development community for nearly 30 years. Hailing from Australia, Chris has a background in Mathematics, Astrophysics, Environmental Engineering and Defence Research. His programming endeavours span everything from FORTRAN on Super Computers, C++/MFC on Windows, through to to high-load .NET web applications and Python AI applications on everything from macOS to a Raspberry Pi. Chris is a full-stack developer who is as comfortable with SQL as he is with CSS.

In the late 1990s, he and his business partner David Cunningham recognized the need for a platform that would facilitate knowledge-sharing among developers, leading to the establishment of CodeProject.com in 1999. Chris's expertise in programming and his passion for fostering a collaborative environment have played a pivotal role in the success of CodeProject.com. Over the years, the website has grown into a vibrant community where programmers worldwide can connect, exchange ideas, and find solutions to coding challenges. Chris is a prolific contributor to the developer community through his articles and tutorials, and his latest passion project, CodeProject.AI.

In addition to his work with CodeProject.com, Chris co-founded ContentLab and DeveloperMedia, two projects focussed on helping companies make their Software Projects a success. Chris's roles included Product Development, Content Creation, Client Satisfaction and Systems Automation.

Comments and Discussions

 
GeneralNice example! Pin
William GS6-Aug-03 7:08
William GS6-Aug-03 7:08 
GeneralPrinting the contents of a CEdit control Pin
Anonymous4-Jun-03 21:00
Anonymous4-Jun-03 21:00 
GeneralRe: Printing the contents of a CEdit control Pin
Jonathan Craig19-Jun-03 4:00
Jonathan Craig19-Jun-03 4:00 
GeneralAbout Date in vc++ Pin
Omarhh15-May-03 7:38
Omarhh15-May-03 7:38 
Generalcool Pin
kreep24-Apr-03 0:50
kreep24-Apr-03 0:50 
GeneralChange page size Pin
accarvajal27-Feb-03 9:29
accarvajal27-Feb-03 9:29 
GeneralRe: Change page size Pin
Jonathan Craig17-Jun-03 3:55
Jonathan Craig17-Jun-03 3:55 
Questionfor me it works on win2k but not on win98 ...?? Pin
Qadddd29-Jan-03 7:45
Qadddd29-Jan-03 7:45 
In order to print a Mschart from a dialog, I wanted to use this way of printing. I finally succeed to make it work or almost work ...
In fact everything works well (it prints !) on my development PC (win2k, quite recent, with all visual studio stuff) but nothing is printed on another PC (win98, much older, and just with the 2 files -.ocx and .dll- added for MSchart). It's not the same printer too but the one connected to the old PC is an epson stylus 760 supposed to be able to perform the StretchBlt.
Here my code launched when the Print button is clicked :
void CGraphDlg::OnEssai()
{
CDC dc;
BOOL ok;
// order chart to copy itself onto clipboard
m_Chart.EditCopy();
CloseClipboard();
// make sure the item in clipboard is a bitmap
if(IsClipboardFormatAvailable(CF_BITMAP))
{
if(OpenClipboard())
{
m_hbitmap = (HBITMAP)::GetClipboardData(CF_BITMAP);
CloseClipboard();
}
}
// lance l'interface pour l'imprimante
CPrintDialog printDialog(false);
bool bShowPrintDialog = TRUE; //FALSE lance directement l'impression
if (bShowPrintDialog)
{
int r = printDialog.DoModal();
if (r == IDCANCEL) // Get printer settings from user
return;
}
else
{
printDialog.GetDefaults();
}
dc.Attach(printDialog.GetPrinterDC()); // Attach a printer DC
dc.m_bPrinting = TRUE;
CString strTitle; // Get the application title
strTitle.LoadString(AFX_IDS_APP_TITLE);
DOCINFO di; // Initialise print document details
::ZeroMemory (&di, sizeof (DOCINFO));
di.cbSize = sizeof (DOCINFO);
di.lpszDocName = strTitle;
int bPrintingOK = dc.StartDoc(&di); // Begin a new print job
// Get the printing extents and store in the m_rectDraw field of a
CPrintInfo Info;
CString toto;
Info.m_rectDraw.SetRect(0,0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES));
OnBeginPrinting(&dc, &Info); // empty funtion
dc.StartPage(); // begin new page
Info.m_nCurPage = 1;
OnPrint(&dc, &Info); // my "Print page" function
OnEndPrinting(&dc, &Info); // empty funtion
dc.EndPage(); // end new page
dc.EndDoc(); // end a print job
dc.Detach(); // detach the printer DC
}
and here in my OnPrint fctn (based on an example):
void CGraphDlg::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
// Create a text for the title
CString sTitleHeader=_T("My First Chart");
CString toto;
// Get the page size and boundaries
CRect rectPage = pInfo->m_rectDraw;
TEXTMETRIC tm;
CFont font;
CSize textSize;
int cyChar;
// Create the font we will be using
font.CreatePointFont(240, "Arial", pDC);
CFont *pOldFont=pDC->SelectObject(&font);
//Set Margin
rectPage.top+=rectPage.bottom/48;
rectPage.bottom-=rectPage.bottom/48;
rectPage.left+=200;
rectPage.right-=200;
// Get Text size in order to center
pDC->GetTextMetrics(&tm);
textSize=pDC->GetTextExtent(sTitleHeader);
cyChar = tm.tmHeight;
// Draw Text (centered)
pDC->TextOut(((rectPage.right+rectPage.left)/2)-(textSize.cx/2), rectPage.top, sTitleHeader);
rectPage.top += cyChar + cyChar / 4;
// Draw header line divider
pDC->MoveTo(rectPage.left, rectPage.top);
pDC->LineTo(rectPage.right, rectPage.top);
// Go to next line
rectPage.top += cyChar / 4;
if(m_hbitmap)
{
BITMAP bm;
AfxMessageBox ("dans impression bitmap",MB_OK,MB_ICONSTOP);
::GetObject(m_hbitmap, sizeof(BITMAP), &bm);
CSize chartSize(bm.bmWidth, bm.bmHeight);
CDC dcMemory,dcScreen;
dcScreen.Attach(::GetDC(NULL));
// create "from" device context and select the loaded bitmap into it
dcMemory.CreateCompatibleDC(&dcScreen);
dcMemory.SelectObject(m_hbitmap);
// Print at 85% size within left/right margin
CSize printSize;
printSize.cx=(int)(rectPage.right*.85);
printSize.cy=printSize.cx/chartSize.cx*chartSize.cy;
toto.Format ( "cx = %d\ncy = %d\n",printSize.cx,printSize.cy);
AfxMessageBox (toto,MB_OK,MB_ICONSTOP);
// Print chart centered
pDC->StretchBlt( ((rectPage.right+rectPage.left)/2)-(printSize.cx/2),
rectPage.top, printSize.cx, printSize.cy, &dcMemory,
0, 0, chartSize.cx, chartSize.cy, SRCCOPY);
dcMemory.DeleteDC();
}
// Revert and Destroy
pDC->SelectObject(pOldFont);
font.DeleteObject();
}
Do you have an idea of what happens or how to progress in my investigations ?
Do you guess if problem comes from OnPrint routine itself or from the print without Doc/view framework ?
Note : I simplified my OnPrint routine to just print the title and drop the print of MsChart and get same problem, nothing is printed. At EndPage() call, I can see the printer spooler saying "print page 0 on 0 pages" that must not be a good sign ...
Thanks in advance for your help.
DD

Generalprinting directly(using StartDocPrinter/RWitePrinter does not work for landscape print) urgent Pin
Member 202397-Jan-03 19:43
Member 202397-Jan-03 19:43 
GeneralI need your help Pin
accarvajal27-Feb-03 9:44
accarvajal27-Feb-03 9:44 
GeneralRe: printing directly(using StartDocPrinter/RWitePrinter does not work for landscape print) urgent Pin
Anonymous21-Oct-03 3:41
Anonymous21-Oct-03 3:41 
Generalprint from dialog Pin
olis17-Jul-02 22:09
olis17-Jul-02 22:09 
GeneralRe: print from dialog Pin
atul arora24-Aug-03 4:54
atul arora24-Aug-03 4:54 
Generalprint the content of screen as it is to the printer Pin
MINAKANNAN10-Jul-02 18:26
MINAKANNAN10-Jul-02 18:26 
GeneralRe: print the content of screen as it is to the printer Pin
N.K.SINGH1-Oct-03 17:22
N.K.SINGH1-Oct-03 17:22 
GeneralRe: print the content of screen as it is to the printer Pin
meenachi16-Oct-03 17:57
meenachi16-Oct-03 17:57 
GeneralRe: print the content of screen as it is to the printer Pin
JosephJulian4-Feb-05 15:02
JosephJulian4-Feb-05 15:02 
GeneralProblem with show CPrintDialog Pin
6-Jul-02 0:04
suss6-Jul-02 0:04 
GeneralProblems in Debug Mode Pin
13-Jun-02 3:54
suss13-Jun-02 3:54 
GeneralRe: Problems in Debug Mode Pin
Roger Allen24-Jun-02 6:53
Roger Allen24-Jun-02 6:53 
GeneralRe: Problems in Debug Mode Pin
26-Jun-02 0:56
suss26-Jun-02 0:56 
QuestionDC leak? Pin
Roger Allen30-May-02 3:34
Roger Allen30-May-02 3:34 
AnswerRe: DC leak? Pin
Chris Maunder30-May-02 4:02
cofounderChris Maunder30-May-02 4:02 
GeneralRe: DC leak? Pin
Thomas Freudenberg30-May-02 13:02
Thomas Freudenberg30-May-02 13:02 
GeneralLack of intuition !!!!! Pin
12-Dec-01 6:05
suss12-Dec-01 6:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.