CFontDialog shows 60 point font that was initiaized to 12 point Times Roman 
Author Message
 CFontDialog shows 60 point font that was initiaized to 12 point Times Roman

I am trying to change the font for a File>Print menu item and am having
trouble getting the correct correlation between the font size and what is
written on the paper.
I have a ListView and when I print, I am using TextOut() in the OnPrint()
message handler rather than the OnDraw() since my format is completely
different to the view.

I start off creating a font in the App initializer as follows, saving it in
the member variable m_fontPrint:

CRaceApp::CRaceApp()
{
   CPrintDialog prtdlg(TRUE);
    prtdlg.GetDefaults();
    HDC hDC = prtdlg.CreatePrinterDC();

    // nominal 12pt font, times roman
    m_fontPrint.CreatePointFont(120, _T("Times New Roman")
     , CDC::FromHandle(hDC));

    // ?? remove
    LOGFONT lf;
    m_fontPrint.GetObject(sizeof lf, &lf);
    . . .

The last three lines are just to make what has been done visible. When I
look in the "lf" struct, the height at this point is -100.

I implemented a File>ChooseFont menu item which is implemented so:

void
CRaceApp::OnFileChooseFont()
{
    LOGFONT lf;
    m_fontPrint.GetObject(sizeof lf, &lf);

    CPrintDialog dlgPrint(FALSE);
    if(!AfxGetApp()->GetPrinterDeviceDefaults(&dlgPrint.m_pd)) {
        AfxMessageBox(_T("Cannot get printer device defaults"));
        return;
    }
    HDC hdcPrint = dlgPrint.CreatePrinterDC();
    if(hdcPrint == NULL) {
        AfxMessageBox(_T("Cannot get printer device context"));
        return;
    }
    CDC dcPrint;
    dcPrint.Attach(hdcPrint);

    CFontDialog dlg(&lf, CF_PRINTERFONTS, &dcPrint);
    if(dlg.DoModal() == IDOK) {
        m_fontPrint.DeleteObject();
        m_fontPrint.CreateFontIndirect(&lf);
    }

Quote:
}

When the CFontDialog box shows up, the font is listed correctly as "Times
New Roman" but the point size is 60!

When I go to print something, the OnPrint() has been instrumented to allow
examination of the font details as follows:

void
CRaceView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
    // reselect the font into the dc
    CFont* pFontPrint = theApp.GetCurrentFont();
    CFont* pFontOld = pDC->SelectObject(pFontPrint);

    // ?? remove. makes the font details visible
    LOGFONT lf;
    pFontPrint->GetObject(sizeof lf, &lf);

    // ?? remove. makes the printer pixel sizes visible
    TEXTMETRIC tm;
    pDC->GetTextMetrics(&tm);
    . . .

Here as before, the font height in "lf" is -100 and the height from the
TEXTMETRIC, tmHeight is 114.  The printer is an HP1100A with 600 dots per
inch so this is reasonable.

My question is, how can I get the CFontDialog to show a font size that
corresponds to the printer?  There is some conversion going on here that I
don't fully understand. I'd like to be able to choose a font size of 8 and
when it is printed, shows up that size on the paper. At the moment, if I do
this, I need a magnifying glass to read the printout!

Ed
--
Edward E.L. Mitchell
Pharsight Corp.
(508)771-0806
500 Ocean St., Unit 134,
Hyannis, MA 02601



Sun, 30 Jan 2005 03:33:11 GMT  
 CFontDialog shows 60 point font that was initiaized to 12 point Times Roman

Quote:
>When the CFontDialog box shows up, the font is listed correctly as "Times
>New Roman" but the point size is 60!
>My question is, how can I get the CFontDialog to show a font size that
>corresponds to the printer?  There is some conversion going on here that I
>don't fully understand.

Ed,

I suspect the key point you're missing is that the font dialog uses
the screen DPI - not the printer's.

Here's how I've used it:

#define PixelToPointSize(Pix, DPI) (((Pix)*72 + (DPI)/2)/(DPI))
#define PointSizeToPixel(Point, DPI) (-MulDiv( Point, DPI, 72 ) )

        if ( lf.lfHeight != 0 )
        {
                dlg.m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;

                /* Convert the point size to pixels */
                /***** The LOGFONT height used here uses the screen
DPI rather than the printers ****/
                HDC hDispDC = ::GetDC( m_hWnd );

                lf.lfHeight = PointSizeToPixel( lf.lfHeight,
GetDeviceCaps( hDispDC, LOGPIXELSY ) ) / 10;

                ::ReleaseDC( m_hWnd, hDispDC );
        }
        if ( dlg.DoModal() == IDOK )

Dave
--
MVP VC++ FAQ: http://www.mvps.org/vcfaq
My address is altered to discourage junk mail.
Please post responses to the newsgroup thread,
there's no need for follow-up email copies.



Sun, 30 Jan 2005 08:11:16 GMT  
 CFontDialog shows 60 point font that was initiaized to 12 point Times Roman
That makes a difference. Thanks for the feedback. I picked up the screen
whole screen DC for the conversion since I'm doing this in the app, not a
view.

However, in trying to cope with different printers, there seems to be a
problem with the divide by ten.

Twelve point font on the printer (600dpi) shows up as an lfHeight of -100
(12*600/72). Converting this to the screen via (100*120/72)/10 is 16.7,
rounded down to 16. When this height is shown in the dialog box, it shows up
as 10 point.

To be exact, I think that I need both the pix/inch of the printer and the
pix/inch of the screen. When the user has a 1200 dot/inch printer, I would
want the font to still show up as 12 point.  I think (hope) the following
does that:

// use these for the font chooser since it works in screen coordinates
#define PIX2PIX(pix, dpiTo, dpFrom)(MulDiv(pix, dpiTo, dpFrom))
. . .
void CRaceApp::OnFileChooseFont()
{
    CPrintDialog dlgPrint(FALSE);
    if(!AfxGetApp()->GetPrinterDeviceDefaults(&dlgPrint.m_pd)) {
        AfxMessageBox(_T("Cannot get printer device defaults"));
        return;
    }
    HDC hdcPrint = dlgPrint.CreatePrinterDC();
    if(hdcPrint == NULL) {
        AfxMessageBox(_T("Cannot get printer device context"));
        return;
    }
    CDC dcPrint;
    dcPrint.Attach(hdcPrint);
    // get the device context for the entire screen
    CDC dcScreen;
    dcScreen.Attach(::GetDC(NULL));

    int iPixScreenPerInch = GetDeviceCaps(dcScreen, LOGPIXELSY);
    int iPixPrintPerInch = GetDeviceCaps(dcPrint, LOGPIXELSY);
    // map initial print log font to screen metrics
    lf.lfHeight = PIX2PIX(lf.lfHeight, iPixScreenPerInch, iPixPrintPerInch);

    CFontDialog dlg(&lf
        , CF_PRINTERFONTS | CF_INITTOLOGFONTSTRUCT, &dcPrint);
    if(dlg.DoModal() == IDOK) {
        // map back to the printer metrics. ?? should the width also change
        lf.lfHeight = PIX2PIX(lf.lfHeight, iPixPrintPerInch,
iPixScreenPerInch);
        m_fontPrint.DeleteObject();
        m_fontPrint.CreateFontIndirect(&lf);
    }
    ::ReleaseDC(NULL, dcScreen.Detach());

Quote:
}

Ed


Quote:
> >When the CFontDialog box shows up, the font is listed correctly as "Times
> >New Roman" but the point size is 60!

> >My question is, how can I get the CFontDialog to show a font size that
> >corresponds to the printer?  There is some conversion going on here that
I
> >don't fully understand.

> Ed,

> I suspect the key point you're missing is that the font dialog uses
> the screen DPI - not the printer's.

> Here's how I've used it:

> #define PixelToPointSize(Pix, DPI) (((Pix)*72 + (DPI)/2)/(DPI))
> #define PointSizeToPixel(Point, DPI) (-MulDiv( Point, DPI, 72 ) )

> if ( lf.lfHeight != 0 )
> {
> dlg.m_cf.Flags |= CF_INITTOLOGFONTSTRUCT;

> /* Convert the point size to pixels */
> /***** The LOGFONT height used here uses the screen
> DPI rather than the printers ****/
> HDC hDispDC = ::GetDC( m_hWnd );

> lf.lfHeight = PointSizeToPixel( lf.lfHeight,
> GetDeviceCaps( hDispDC, LOGPIXELSY ) ) / 10;

> ::ReleaseDC( m_hWnd, hDispDC );
> }
> if ( dlg.DoModal() == IDOK )

> Dave
> --
> MVP VC++ FAQ: http://www.mvps.org/vcfaq
> My address is altered to discourage junk mail.
> Please post responses to the newsgroup thread,
> there's no need for follow-up email copies.



Mon, 31 Jan 2005 17:58:44 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. How to use Times New Roman and Aarial Fonts in eVC++

2. Am I copying or pointing?

3. floating point rounding or floating point printing ?

4. To point or not to point

5. Implicit decimal points in floating-point reads

6. 60 seconds is a long time

7. Converting floating point to scaled fixed point

8. need 64-point and 256-point integer-only FFT

9. Internet Point to Point

10. Points to Pixels, Points to HIMetric

11. What is 12 pt. font

12. Set Precision and Show Point in MFC

 

 
Powered by phpBB® Forum Software