Link to home
Start Free TrialLog in
Avatar of carlpaddick
carlpaddick

asked on

Font is printing too small on the printer

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
then
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);

   pDC->GetTextMetrics(&tm);

   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.
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nietod
nietod

>> 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.
Avatar of carlpaddick

ASKER

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
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....)
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
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...
>> 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.
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.
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:

   pDC->SetMapMode(MM_TWIPS);
   pDC->SetMapMode(MM_ANISOTROPIC);
   myFont.CreateFont(lf.lfHeight, lf.lfWidth,....

Is this correct, or am I doing something wrong?
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.
>>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 ;-)
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.