Click here to Skip to main content
Click here to Skip to main content

Printing without the Document/View framework

By , 29 May 2002
 

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)

About the Author

Chris Maunder
Founder CodeProject
Canada Canada
Member
Chris is the Co-founder, Administrator, Architect, Chief Editor and Shameless Hack who wrote and runs The Code Project. He's been programming since 1988 while pretending to be, in various guises, an astrophysicist, mathematician, physicist, hydrologist, geomorphologist, defence intelligence researcher and then, when all that got a bit rough on the nerves, a web developer. He is a Microsoft Visual C++ MVP both globally and for Canada locally.
 
His programming experience includes C/C++, C#, SQL, MFC, ASP, ASP.NET, and far, far too much FORTRAN. He has worked on PocketPCs, AIX mainframes, Sun workstations, and a CRAY YMP C90 behemoth but finds notebooks take up less desk space.
 
He dodges, he weaves, and he never gets enough sleep. He is kind to small animals.
 
Chris was born and bred in Australia but splits his time between Toronto and Melbourne, depending on the weather. For relaxation he is into road cycling, snowboarding, rock climbing, and storm chasing.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionPrinting without the Document/View frameworkmemberkimba1111 Sep '12 - 6:41 
Chris,
 
Do you happen to have a working example of "Printing without the Document/View framework"? In exchange I will gladly supply you with a working and documented example of (your choice either for your personal use or for you to publish):
ISAPI Filter or Extension
ISAPI was dropped in Windows
Server 2008 wait for its
subsequent revision .
Error trapping in MySQL
Preferred to MSSQL, closer
to my UNIX roots.

 
Kimball
Chris use my account info to email me
GeneralTerrific!memberMike Gaskey6 Dec '11 - 9:49 
I just incorporated this logic into project where I had multiple FormView based views (tabbed views) embedded in tabbed CScrollView based views (multiple document types), all of which made the use of the normal print logic of a doc/view app impossible to use. I actually found the code at its original location, CodeGuru, via a google search and when I saw the author realized I could find it here as well. Really solved a problem for me. Thanks Chris!
Mike - typical white guy.
 
"Political correctness is a doctrine, fostered by a delusional, illogical minority, and rabidly promoted by an unscrupulous mainstream media, which holds forth the proposition that it is entirely possible to pick up a piece of sh*t by the clean end."
 
Thomas Mann - "Tolerance becomes a crime when applied to evil."
 
As American as: hot dogs, apple and Sarah Palin.

GeneralRe: Terrific!adminChris Maunder6 Dec '11 - 9:50 
Talk about a blast from the past!
cheers,
Chris Maunder
 
The Code Project | Co-founder
Microsoft C++ MVP

Generalmemory leakmemberlichongbin7 Mar '11 - 22:56 
when you preview your document, a new document template is added to the template list without deleting it.
m_pTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
NULL,
RUNTIME_CLASS(CFrameWnd),
RUNTIME_CLASS(CViewPrintPreview));
AfxGetApp()->AddDocTemplate(m_pTemplate);
There is a will,there is a way!

QuestionHow should i use this way to print a Recordset ?membersofe_Jane26 Nov '09 - 21:06 
hi,
 
I want to implement a print function , but i dont know how to do . Frown | :(
 
I select the sql data ,and the result is in a Recordset and I use the DataGrid to show them on a dialog.
 
then at this dialog ,I want to add a button which can let me print the data on paper
 
Could you give me some advice ?
 
thanks ,
 
Jane
QuestionHow to programmatically make the printing fail through OnPrintmemberel davo25 Aug '08 - 17:18 
Howdy,
 
I see that the code tests if the printing is OK based on whether the dc.EndPage() function returns > 0.
 
Say for example my OnPrint function fails to to a StretchBlt - I'd like to somehow make the EndPage return zero.
 
--- Is there a way to do this, or should I just call dc.AbortDoc()? ---
 
Calling AbortDoc seems to be incorrect, as the bPrintingOK flag then tells us to AbortDoc anyway.
 
Cheers,
 
Dave

Questionwhat is AFX_IDS_APP_TITLE?memberkamal21 Nov '06 - 22:39 
what is AFX_IDS_APP_TITLE? How can i set this value.
 
My Application is dialog based. I want to print some set of documents without opening.
 
I have the documents names only in my application. Where can i set these documents name in this program? How can i get print dialog and settings for these documents?
 
Confused | :confused: Waiting for reply.
 
Thank You.
 

AnswerRe: what is AFX_IDS_APP_TITLE?memberS Douglas28 Nov '06 - 23:07 
kamal wrote:
what is AFX_IDS_APP_TITLE? How can i set this value.

 
Did you read the article? See the text in bold.
    CString strTitle;                       // Get the application title
    strTitle.LoadString(AFX_IDS_APP_TITLE);
 
AFX_IDS_APP_TITLE, is the resource constant for the Application's title.
 


I'd love to help, but unfortunatley I have prior commitments monitoring the length of my grass. :Andrew Bleakley:


GeneralRe: what is AFX_IDS_APP_TITLE?memberkamal29 Nov '06 - 22:50 
thanks!..... but,
 
1. i want to print a document by location name like d:\abcd.doc
2. i want to set the properties for that document and printer also.
3. my application is fully dialog based.
 
reply me.
Confused | :confused:

GeneralRe: what is AFX_IDS_APP_TITLE?memberS Douglas30 Nov '06 - 4:05 
kamal wrote:
1. i want to print a document by location name like d:\abcd.doc

 
So what does this have to do with your original question?
 
Word Documents are in a propriety format, if you want to print a word document your going to need to delve into word /office automation.

 

 


I'd love to help, but unfortunatley I have prior commitments monitoring the length of my grass. :Andrew Bleakley:


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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 30 May 2002
Article Copyright 1999 by Chris Maunder
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid