Font is printing too small on the printer

Posted on 1999-06-22
Medium Priority
Last Modified: 2013-12-02
Please help me guys as soon as you can!!!

I am trying to print text from a given font on a 600 dpi printer that has been:

1. Created through a predefined LOGFONT structure
2. Selected into the Printer's Display Context

The point size of the font is calculated from the above, but its tiny, and when the characters print, you need an eye test!  Here's my code below:

// Convert Logical Height to Point size
CDC* pDC = GetDC();
if (tempFont.CreateFontIndirect(&m_LogFont))
   CFont* pOldFont = pDC->SelectObject(&tempFont);


   int nPointSize = MulDiv((INT) tm.tmHeight -  tm.tmInternalLeading, 72, pDC->GetDeviceCaps (LOGPIXELSY));


If you use the monitor's Display Context, the Point Size is calculated correctly , however on the printer its tiny.  Any suggestions?  Thanks.
Question by:carlpaddick
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
  • 4
  • 3
LVL 86

Accepted Solution

jkr earned 600 total points
ID: 1198122
You'll have to create the font based upon the resolution of the printer's device context in order to work correctly, e.g.

//Get Text Height
dwExtent   = cPrintDC.GetTextExtent("0",1);
nTxtHeight = (int)((dwExtent&0xFFFF0000)/0x10000);
nMapFactor = nTxtHeight/14; // Standard printer font is assumed to be a
                      // 14 dot screen font

    lf.lfHeight    = SavedFont.lfHeight*nMapFactor;
    lf.lfWidth     = SavedFont.lfWidth*nMapFactor;
    lf.lfUnderline = 0;
    lf.lfQuality   = PROOF_QUALITY;

 hFont    = CreateFontIndirect(&lf);
 hOldFont = cPrintDC.SelectObject(hFont);

Feel free to ask if you need more information!
LVL 22

Expert Comment

ID: 1198123
>> You'll have to create the font based upon the resolution
>> of the printer's device context in order to work correctly
This is becuase the printer DC (all DCs) defaults to the text mapping mode.  This mapping mode maps each logical unit (like the font size specified in the LOGFONT) to a single pixel.  Thus in this mode, the size of the results depend on the resolution of the device

An alternative to jkr's solution is to let windows do the calculations for you by changing to a different mapping mode.  For example, you could change to TWIPS (commonly used for printing) and then specify your font hight in twips (1/1440 of an inch (or 1/72 of a point)).  The OS will automatically scale the font (and everything else) so that it appears in the size you requested regardless of the resolution of the device you are printing to.

Author Comment

ID: 1198124
I have just tried jkr's suggestion.
I presume the variable in the line

   dwExtent = cPrintDC.GetTextExtent("0",1);

is of CSize type?  However the next line below it

  nTxtHeight = (int)((dwExtent&0xFFFF0000)/0x10000);

doesn't seem to compile if you use dwExtent as a CSize type.
Am I typing this incorrectly?  What I am currently doing is to use the '.cy' member of CSize and multiply (is that supposed to be * or &) it with 0xFFFF0000.  Now the font is HUGE.  Please help.  Thanks
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 22

Expert Comment

ID: 1198125
I'm not sure why he is doing that, but

nTxtHeight = dwExtent.cy;

should be fine.  At least as far as I can tell.   (But I recomend you reconsider my suggestion, let windows do this work for you.  It does the same thing as you are trying to do.  But its been written and tested....)

Author Comment

ID: 1198126
Hmmm, the font is still coming out HUGE even if I use the

   nTxtHeight = dwExtent.cy;

modified line.  I'm going to try changing the mapping mode to MM_TWIPS.  After I've done that in my printer DC, do I need to alter my LOGFONTS' .lfHeight member (ie dividing it by 72)?  Also I need to change the ExtTextOut() calls to have negative 'y' coordinates and not positive ones.  Is this correct? Could you give me some example code nietod please?  Thanks
LVL 86

Expert Comment

ID: 1198127
Sorry for the inconvenience,

but I copied the code above from an onld Win16 project where 'GetTextExtent()' once was an API functtion and returned a DWORD...

Adapted to MFC, it should read

//Get Text Height
CSize cExtent;
cExtent   = cPrintDC.GetTextExtent("0",1);
nTxtHeight = cExtent.cy;

without any multiplication...
LVL 22

Expert Comment

ID: 1198128
>> do I need to alter my LOGFONTS' .lfHeight
>> member (ie dividing it by 72)
Probably not dividing.  a TWIP is 1/72 of a point.  so a 12 point font is 12*72 TWIPS  (twips are very small, so dimensions expressed in twips tend to be very big.  An 8X11 piece of paper is over 15,000 twips tall.  So twips are very precise too.)

>> Also I need to change the ExtTextOut() calls to
>>  have negative 'y' coordinates and not positive ones
yes I beleive that is correct.  The origin will be the top-left corner of the printable area and coordinates below that will be at negative y's.   If you don't like that (I don't) you can use the ANISOTROPIC mode to express things in TWIPS but to have the coordinates below the origin at positive y values.
LVL 22

Expert Comment

ID: 1198129
The code I have is not MFC and (worse) it does use a class library so it is not going to be too usefull.  In addition it uses the ANISOTROPIC mode so that postiive y goes down the page.   However, I can post it if you want.

Author Comment

ID: 1198130
Thanks for the information that you're passing on to me guys.  Its becoming really useful.

Right then, I've tried working with your formula jkr.  This seems to work but dividing by 14 renders the font a little taller and wider than MS Word's font.  I have used MS Sans Serif 10 as an example in the logfont.  Is this normal?

Secondly I've also tried your suggestion nietod using MM_TWIPS and MM_ANISOTROPIC but nothing prints out - I just get blank sheets of paper.  My code is as follows:

   myFont.CreateFont(lf.lfHeight, lf.lfWidth,....

Is this correct, or am I doing something wrong?
LVL 22

Expert Comment

ID: 1198131
If you want to use anisotropic you need to set the viewport extent and window extent using SetViewPortExtEx() and SetWindowExtExt().  These set up the "scale" you want to use.  The value viewport extent is the number of device units (pixels) that you want to have scale to the number of logical unts (twips, for example) specified window in the window extent.  You can set the viewport extent to the number of pixels per inch (get from GetDeviceCaps())  and the window extent to the number of logical units per inch you want (like 1440 for working with TWIPS).   Does that make sense  However, if these  values are too large, (as they are in my example if used on a high-resolution printer), they will cause weird behavior in windows 9x because it uses a 16 bit GDI (they are fine in NT.)  So if the device has high resolution, like a laser printer, divide the values a bit to make them smaller.
LVL 86

Expert Comment

ID: 1198132
>>This seems to work but dividing by 14

Yes, the division by 14 is based on the fact that the original screen font was 14pts - if you're using a 10pts font, divide by 10 ;-)

Author Comment

ID: 1198133
Right, I've finally come up with a solution but unfortunately it doesn't incorporate any of your suggestions guys, not that I'm not grateful.  I will certainly use those in future tasks.

What I'm working on at the moment is user driven.  Commenting on your last comment jkr, I did not know what the point size of the current font was - all I had was a populated LOGFONT structure.  Your last comment nietod is a bit too complex for me to understand, although with experimentation would suffice.  The solution I have come up with, is to store the point size along with the LOGFONT for each object (I'm working on a Report Writer tool) and then call 'CreateFont' muliplying the point size by the number of dots per inch and dividing by 72, for example:

   CreateFont(m_nObjPtSize * m_ndpi / 72, lf.lfWidth....

This seems to work.

I would like to split the points between both of you because you've been really helpful.  Thanks once again.


Featured Post

Industry Leaders: 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

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Ever visit a website where you spotted a really cool looking Font, yet couldn't figure out which font family it belonged to, or how to get a copy of it for your own use? This article explains the process of doing exactly that, as well as showing how…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

719 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