Click here to Skip to main content
11,570,759 members (59,315 online)
Click here to Skip to main content

Printing support functions

, 6 Feb 2000 CPOL 195.3K 48
Rate this:
Please Sign up or sign in to vote.
Two methods for obtaining consistent output between printers.

Introduction

Using the default properties supplied for printer output does not give consistent results. The printable region and the pixel density cause variations. If you are outputting pages for a formal report, consistent margins and font size are often required. The following functions provide a method for obtaining consistent output between printers.

Included functions are:

  1. UserPage which returns a CRect which defines a consistent printable area for each printer (Your margins must be within the printable region of all printers of course!)
  2. CreateFontSize which returns a CSize which defines the font attribute with respect to the desired point size and printer characteristics.

The remaining code shows sample usage of these functions.

//Input: pointer to device context for printer
//Input: desired margin
//Output: CRect to use for printing area
CRect CChildView::UserPage(CDC * pDC, float margin)
{
    // This function returns the area in device units to be used to
    // prints a page with a true boarder of "margin".
    //
    // You could use individual margins for each edge
    // and apply below as needed.
    //
    // Set Map Mode - We do not want device units
    // due to lack of consistency.
    // If you do not use TWIPS you will have to change
    // the scaling factor below.
    int OriginalMapMode = pDC->SetMapMode(MM_TWIPS);

    // Variable needed to store printer info.
    CSize PrintOffset,Physical,Printable;

    // This gets the Physical size of the page in Device Units
    Physical.cx = pDC->GetDeviceCaps(PHYSICALWIDTH);
    Physical.cy = pDC->GetDeviceCaps(PHYSICALHEIGHT);
    // convert to logical
    pDC->DPtoLP(&Physical);

    // This gets the offset of the printable area from the
    // top corner of the page in Device Units
    PrintOffset.cx = pDC->GetDeviceCaps(PHYSICALOFFSETX);
    PrintOffset.cy = pDC->GetDeviceCaps(PHYSICALOFFSETY);
    // convert to logical
    pDC->DPtoLP(&PrintOffset);

    // Set Page scale to TWIPS, Which is 1440 per inch,
    // Zero/Zero is the upper left corner
    // Get Printable Page Size (This is in MM!) so convert to twips.
    Printable.cx =  (int)((float)pDC->GetDeviceCaps(HORZSIZE)*56.69);
    Printable.cy = (int)((float)pDC->GetDeviceCaps(VERTSIZE)*56.69);

    // Positive X -> RIGHT
    // Positive Y -> UP
    // Ref Zero is upper left corner
    int inch = 1440; // Scaling Factor Inches to TWIPS
    int Dx1, Dx2, Dy1, Dy2; // Distance printable area is from edge of paper
    Dx1 = PrintOffset.cx;
    Dy1 = PrintOffset.cy;
    // calculate remaining borders
    Dy2 = Physical.cy-Printable.cy-Dy1;
    Dx2 = Physical.cx-Printable.cx-Dx1;
    //
    // Define the User Area's location
    CRect PageArea;
    PageArea.left = (long)(margin*inch-Dx1);
    PageArea.right = (long)(Printable.cx-margin*inch+Dx2);
    PageArea.top = (int)-(margin*inch-Dy1); // My scale is inverted for y
    PageArea.bottom = (int)-(Printable.cy-margin*inch+Dy2);
    // now put back to device units to return to the program.
    pDC->LPtoDP(&PageArea);
    //
    // return
    return PageArea;
}
// Input: pointer to device context for printer
// Input: desired point size of font (in points).
// Output: integer height to send to CreateFont function.
int CChildView::CreateFontSize(CDC *pdc, int points)
{
    // This will calculate the font size for the printer that is specified
    // by a point size.
    //
    // if points is:
    //  (-) negative uses height as value for Net Font Height
    //                                         (ie. point size)
    //  (+) positive height is Total Height plus Leading Height!
    CSize size;
    int perinch = pdc->GetDeviceCaps(LOGPIXELSY);
    size.cx = size.cy = (perinch*points)/72;
    pdc->DPtoLP(&size);
    return size.cy;
}

To use CreateFontSize, just insert the function call into the CreateFont function:

    BaseFont.CreateFont( -CreateFontSize(pdc,11), 0, 0, 0, FW_MEDIUM,
        FALSE, FALSE, 0, ANSI_CHARSET, 
        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 
        DEFAULT_QUALITY, DEFAULT_PITCH , "Courier New" );

The UserPage function can be used internal to your OnPrint function. Where you call it, use the returned area rather than the region found from the pDC's GetDeviceCaps function. (Usually sent in the PrintInfo data.) Or you can call it to set the region in to be passed.

void CChildView::PrintSetup(int item)
{
    // Create Standard windows dialog.
    BOOL bStdSetUpDlg = TRUE;
    // See PRINTDLG for flags to set defaults in dialog.
//    DWORD dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES | 
         PD_NOPAGENUMS | PD_HIDEPRINTTOFILE | PD_NOSELECTION;
    DWORD dwFlags = PD_ALLPAGES;
    // Parent (may be NULL)
    CWnd *pParent = this;
    CPrintDialog MyPrintDlg(bStdSetUpDlg,dwFlags,pParent);
    // Print Info
    CPrintInfo MyPrintInfo;
    // first link with dialog so data is shared
    // Your input into min and max pages is now shared.
    MyPrintInfo.m_pPD = &MyPrintDlg;
    //
    // Get Users Answer;
    int MyAnswer;
    MyAnswer = MyPrintDlg.DoModal();
    // Allow the user to cancel
    if(MyAnswer==IDCANCEL) return;
    //
    // Get the mode the printer is in from the Print Dialog.
    // This memory block must be unlocked later.
    DEVMODE *MyPrintMode;
    MyPrintMode = MyPrintDlg.GetDevMode();
    // 
    // Create our Printer Context
    CDC MyPrintDC;
    MyPrintDC.CreateDC(MyPrintDlg.GetDriverName(), // Ignored for Printer DC's
        MyPrintDlg.GetDeviceName(), // The only required item for Printer DC's
        MyPrintDlg.GetPortName(), // Ignored for Printer DC's
        MyPrintMode); // Optional Item for Printer DC's
    //
    // Start the Document for our document
    DOCINFO MyDocInfo;
    MyDocInfo.cbSize=sizeof(DOCINFO);
    CString DocName;
    DocName.LoadString(AFX_IDS_APP_TITLE);
    MyDocInfo.lpszDocName="DocName";
    MyDocInfo.lpszOutput="";
    //
    // Start the document
    int iErr = MyPrintDC.StartDoc(&MyDocInfo);
    if(iErr < 0)
    {
        //success returns positive value
        MyPrintDC.AbortDoc();
        GlobalUnlock(MyPrintMode); // Release the print mode.
        return;
    }
    // success so set flag to printing
    MyPrintDC.m_bPrinting=TRUE;
    // Most programs us the device's printable region found with
    // MyPrintDC.GetDevicecaps(****) functions.
    // However this is not consistent between printers so -->
    // The UserPage functions calculates what margins
    // to specify so we have the
    // actual distance from the edge of the page
    // to be consistent between printers.
    CRect MyArea;
    // fixed margin in inches (you can change this)
    MyArea = UserPage(&MyPrintDC, 0.9f);
    MyPrintInfo.m_rectDraw.SetRect(MyArea.left, 
            MyArea.top,MyArea.right,MyArea.bottom);
    //
    // We are now into personal preferences based on your program needs.
    //
    // We can call OnBeginPrinting and OnEndPrinting functions
    // to initialize and clean up
    // and loop through calls to OnPrint
    // (calling Startpage and EndPage functions)
    //
    // or as I have done here->
    // Call the StartPage the first time EndPage at the end
    // with the print fnuction handling the begin
    // and end when needed internally.
    //
    // Start the page. (This allways sets the DC to device units!) 
    MyPrintDC.StartPage();
    // Set mode.
    MyPrintDC.SetMapMode(MM_TEXT);
    //
    // We are now ready to print our data. Switch to the options allowed.
    // For our usage we will end and restart
    // each page in the functions called
    // based on the location of the current print location on the page.
    //
    // Internal to the fucntions we need to call:
    //     pdc->EndPage();
    //    pdc->StartPage(); // Returns in Device units
    //    pdc->SetMapMode(MM_LOENGLISH); // Reset to our desired mode
    //  Reset position to draw, etc....
    // as needed.
    //
    switch(item)
    {
    case(1):
        PrintLoose(&MyPrintDC,MyArea);
        break;
    case(2):
        PrintRecord(&MyPrintDC,MyArea);
        break;
    }
    // We are all done. Clean up
    MyPrintDC.m_bPrinting=FALSE;
    // end last page
    MyPrintDC.EndPage();
    // end the document
    MyPrintDC.EndDoc();
    // Release the device context
    GlobalUnlock(MyPrintMode); // Release the print mode.
    return;
}

License

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

Share

About the Author

Michael A. Barnhart
Systems Engineer
United States United States
Began programming in 1968 on a Wang 720. Move to Fortran and began developing FEM (finite element model) applications on an IBM 360 in 1973. Developed custom FEM editors for most of my career until 1995. Since then I have been focusing on improving information flow and quality with web based communications (Web Services and SOA concepts.) Mostly in an evangelist role.

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
manoj kumar choubey18-Feb-12 0:09
membermanoj kumar choubey18-Feb-12 0:09 
Generalprinter service on C#.net Pin
balu1234530-Jul-08 7:39
memberbalu1234530-Jul-08 7:39 
GeneralNeed Help Pin
cs0248013-Sep-07 22:23
membercs0248013-Sep-07 22:23 
QuestionCan MFC Dialog base support printing Pin
wangsus14-Jun-06 8:23
memberwangsus14-Jun-06 8:23 
GeneralPrint Pin
Seu_why28-Mar-06 16:01
memberSeu_why28-Mar-06 16:01 
Generalprint Pin
amitrajin02@gmail.com5-Sep-05 0:50
memberamitrajin02@gmail.com5-Sep-05 0:50 
GeneralPrinter Consistence in Visual Basic Pin
e_screw21-Jul-05 3:33
membere_screw21-Jul-05 3:33 
Hi , Thanks all.
I have developed an application in visual basic which prints on pre defined papers. My problem is when i print the content on EPSON InkJet/DeskJet its printing fine. But when i use another printer like HP Laser Printer its not printing on the paper( printing outside). My paper is very small (18cms x 10cms). In laser printer, when i keep the paper and move the lever to make paper not to move, its coming to the center of the tray. And when i print its printing in the left margin or right margin, where there is no paper and my paper in center! Could any one plz help me how to make it print in the center?

I have seen the code here By M.A Barnhart, but i couldnot understand the code except the GETDEVICECAPS. Could anyone plz help me doing the same in visual basic, if its the solution i am looking for.

Thanks in advance


Thanks in advance

Electronic Screw
GeneralCrashes when destructing Pin
panzerdivisionmarkus14-Jul-05 20:51
memberpanzerdivisionmarkus14-Jul-05 20:51 
GeneralRe: Crashes when destructing Pin
Michael A. Barnhart15-Jul-05 0:05
memberMichael A. Barnhart15-Jul-05 0:05 
GeneralRe: Crashes when destructing Pin
panzerdivisionmarkus15-Jul-05 1:54
memberpanzerdivisionmarkus15-Jul-05 1:54 
GeneralIntercepting a print job Pin
AlexEvans2-Jul-05 16:40
memberAlexEvans2-Jul-05 16:40 
GeneralRe: Intercepting a print job Pin
Michael A. Barnhart3-Jul-05 1:00
memberMichael A. Barnhart3-Jul-05 1:00 
GeneralRestore to original MapMode Pin
David_Leikis26-May-05 6:07
memberDavid_Leikis26-May-05 6:07 
GeneralRe: Restore to original MapMode Pin
Michael A. Barnhart26-May-05 10:52
memberMichael A. Barnhart26-May-05 10:52 
QuestionHow to change the size of a print page? Pin
deer@webmail.hebut.edu.cn22-Apr-05 23:15
memberdeer@webmail.hebut.edu.cn22-Apr-05 23:15 
AnswerRe: How to change the size of a print page? Pin
Michael A. Barnhart22-Apr-05 23:56
memberMichael A. Barnhart22-Apr-05 23:56 
QuestionHow to print the image keeping it's original size without considering the size of page, Pin
MasterFan20-Oct-04 22:48
memberMasterFan20-Oct-04 22:48 
Generalline thickness Pin
ssoft24-Sep-03 19:36
memberssoft24-Sep-03 19:36 
Questionhow to get a printer job is color or not? Pin
tw_vincent18-Jul-03 6:33
membertw_vincent18-Jul-03 6:33 
GeneralExcellent Code, Help Wanted... Pin
asharveyuk9-Feb-03 6:35
memberasharveyuk9-Feb-03 6:35 
GeneralRe: Excellent Code, Help Wanted... Pin
Michael A. Barnhart9-Feb-03 6:59
memberMichael A. Barnhart9-Feb-03 6:59 
GeneralStartDoc() not working for Release Pin
lucky76020-Jan-03 12:02
memberlucky76020-Jan-03 12:02 
GeneralRe: StartDoc() not working for Release Pin
Michael A. Barnhart20-Jan-03 12:18
memberMichael A. Barnhart20-Jan-03 12:18 
Generalquestion about CPrintDialog and DEVMODE Structure Pin
lavocat2-Dec-02 0:20
memberlavocat2-Dec-02 0:20 
GeneralRe: question about CPrintDialog and DEVMODE Structure Pin
Michael A. Barnhart2-Dec-02 12:40
memberMichael A. Barnhart2-Dec-02 12:40 
GeneralRe: question about CPrintDialog and DEVMODE Structure Pin
lavocat2-Dec-02 21:41
memberlavocat2-Dec-02 21:41 
GeneralRe: question about CPrintDialog and DEVMODE Structure Pin
Michael A. Barnhart3-Dec-02 0:26
memberMichael A. Barnhart3-Dec-02 0:26 
GeneralPageArea Calc Pin
cdoersom26-Nov-02 10:22
membercdoersom26-Nov-02 10:22 
GeneralRe: PageArea Calc Pin
Michael A. Barnhart26-Nov-02 13:17
memberMichael A. Barnhart26-Nov-02 13:17 
GeneralRe: PageArea Calc Pin
cdoersom26-Nov-02 18:48
membercdoersom26-Nov-02 18:48 
GeneralRe: PageArea Calc Pin
Michael A. Barnhart27-Nov-02 0:11
memberMichael A. Barnhart27-Nov-02 0:11 
GeneralRe: PageArea Calc Pin
cdoersom27-Nov-02 6:04
membercdoersom27-Nov-02 6:04 
GeneralRe: PageArea Calc Pin
Michael A. Barnhart27-Nov-02 12:59
memberMichael A. Barnhart27-Nov-02 12:59 
GeneralInkjet printers give dpi different Pin
Richard Jones20-Nov-02 4:36
memberRichard Jones20-Nov-02 4:36 
GeneralRe: Inkjet printers give dpi different Pin
Michael A. Barnhart20-Nov-02 13:27
memberMichael A. Barnhart20-Nov-02 13:27 
GeneralRe: Inkjet printers give dpi different Pin
Richard Jones22-Nov-02 2:25
memberRichard Jones22-Nov-02 2:25 
GeneralProb getting color setting from DEVMODE Pin
jcn12319-Apr-02 8:45
memberjcn12319-Apr-02 8:45 
GeneralRe: Prob getting color setting from DEVMODE Pin
i.Wahn25-Jul-02 21:32
memberi.Wahn25-Jul-02 21:32 
GeneralTwo small problems Pin
Tony Brown17-Jul-01 1:11
memberTony Brown17-Jul-01 1:11 
GeneralRe: Two small problems Pin
Michael A. Barnhart17-Jul-01 13:33
memberMichael A. Barnhart17-Jul-01 13:33 
GeneralRe: Two small problems Pin
Duncan123452-Apr-03 1:57
memberDuncan123452-Apr-03 1:57 
GeneralThe same, but slightly different Pin
Joep Oude Veldhuis21-Feb-01 0:29
memberJoep Oude Veldhuis21-Feb-01 0:29 
GeneralGood Pin
raja sekhar18-Feb-01 21:17
memberraja sekhar18-Feb-01 21:17 
GeneralRe: Good Pin
Michael A. Barnhart19-Feb-01 12:10
memberMichael A. Barnhart19-Feb-01 12:10 
GeneralPost Script Printer Pin
navid_ahsan4-Dec-00 16:59
membernavid_ahsan4-Dec-00 16:59 
GeneralIn millimeters !?!?! Pin
Luc Bergeron21-Sep-00 10:46
sussLuc Bergeron21-Sep-00 10:46 
GeneralRe: In millimeters !?!?! Pin
Michael A. Barnhart22-Sep-00 12:18
sussMichael A. Barnhart22-Sep-00 12:18 
GeneralPrinter Differences Pin
Sujay Ghosh16-Jul-00 22:51
sussSujay Ghosh16-Jul-00 22:51 
GeneralRe: Printer Differences Pin
Michael Barnhart17-Jul-00 3:03
sussMichael Barnhart17-Jul-00 3:03 
GeneralMissing Line in UserPage Pin
Michael Barnhart9-Feb-00 6:14
sussMichael Barnhart9-Feb-00 6:14 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150624.2 | Last Updated 7 Feb 2000
Article Copyright 2000 by Michael A. Barnhart
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid