"Joseph M. Newcomer" wrote:
See below...
On Tue, 22 Dec 2009 05:27:01 -0800, Cameron_C <CameronC@discussions.microsoft.com> wrote:
Hello Everyone.
I have been struggling with this item for some time.
For a while I was content to ignore it, but it has finally made it to the
top of my list.
I have an application where the User may choose reporting fonts.
Three fonts. One for the header, one for the body, and one for the footer of
the various reports. I save the LOGFONT structures for later use.
At the time I do a StartDocument I grab the LOGFONT structures I had
previously saved, and CreatePointFontIndirect to create the fonts.
As I walk through the code in debug mode, everything seems to work fine.
However, the printing works perfectly on an HP 9040DN, but no details appear
when I print to a Brother or the HP Photosmart I have. The graphics boxes do
appear though.
Anyway my first question relates to the voodoo-like black magic of scaling
the font.
I want a ten point font. I select a ten point font from the CFontDialog, and
save it. Later, when I want to create the font I call
CreatePointFontIndirect, and I pass a value that is in tenths of a point. So,
now I would pass 100, for my ten point font.
****
The truth is that the font is scaled to the display. If you want to use that font on a
printer, you must scale it to the printer.
Typically, you want to use CFont::CreatePointFontIndirect and for the second parameter
pass in your printer DC for printing and either NULL or your display DC for display.
*****
From experience this never worked. After poking through various web sites, I
found someone had success with using a "Cook''s Constant" of 42/13. So, I
have taken my value of 100, and multipled by 42/13. Is this obtuse or am I
off base here? Anyway, this appears to do the trick, at least for the HP
printer.
****
Sounds like sheer luck. I have no idea what this is doing.
*****
I checked the Microsoft docs, and they suggest using something along the
lines of -MulDiv(m_lfReportHeader.lfHeight/10,
m_dc.GetDeviceCaps(LOGPIXELSY), 72);
Now, I have tried this with the printers that do not deliver the report as
execpted, and I see no difference. I have not tried this with the HP printer
that is really working.
*****
It may be a function of the printer dirvers, but it seems obtuse if it is.
****
Here is a code snippet showing how I have created the fonts.
/*
Assign default Report Header Font for the Reports
Note: m_szIniSectionName will refer to the specific Report for the Printer.
m_ProcessIni.m_szIniSectionName will refer to the DEFAULT entries
for the Printer.
*/
LOGFONT lfIniDefaults;
BOOL bFlag=FALSE;
TEXTMETRIC myTextMetrics;
m_ProcessIni.m_szIniKeyName.LoadString(IDS_REPORTHEADERFONT);
bFlag = m_ProcessIni.getKeyValueForFont(&lfIniDefaults,
m_ProcessIni.m_szIniKeyName, m_szIniSectionName);
****
Have you considered the Registry for this? My Registry library actually saves some font
information automatically. I see no value in parsing font information from a .INI file (I
gave up doing that when I abandoned Win16 many years ago)
****
if (!bFlag) // No font information available from the ini file, so save
DEFAULT
{
m_ProcessIni.setKeyValueForFont(m_plfReportHeader,
m_ProcessIni.m_szIniKeyName, m_szIniSectionName);
}
else
{
m_lfReportHeader = lfIniDefaults;
}
lfIniDefaults = m_lfReportHeader;
lfIniDefaults.lfHeight*=(42/13); // I have no idea why this scaling is
required... But it is. Found this in a news group.
****
Neither do I, it looks really bogus, like someone discovered some random value which gave
the illusion of working so claimed it made sense. 42/13 is silly anyway; 42/13 is 3, and
expressed as 42/13 doesn't change the fact it is 3. And I have no idea what 3 does. Now
42.0/13.0, working as a double, e.g.,
something =(int)( (double) something * 42.0 / 13.0)
might have meaning, but "3" is just silly.
****
// lfIniDefaults.lfHeight = -MulDiv(m_lfReportHeader.lfHeight/10,
m_dc.GetDeviceCaps(LOGPIXELSY), 72);
****
If you get rid of the gratutitous *=3, this should work correctly. But it is what
CreatePointFontIndirect does. Read the code.
****
/*
Establish Font characteristics for the Report Header lines.
lfIniDefaults Points to a LOGFONT structure that defines the
characteristics
of the logical font.
The lfHeight member of the LOGFONT structure is measured in tenths of a
point
rather than logical units.
(For instance, set lfHeight to 120 to request a 12-point font.)
CreatePointFontIndirect returns non-zero when successful.
If bFlag is zero, we have a problem!
*/
CFont*pOldHeaderFont, *pOldFooterFont, *pOldBodyFont;
*****
Never use commas in declaration lists. And there is no reason to save old state like
"OldHeaderFont"; instead, use CDC::SaveDC and CDC::RestoreDC to mainain the purity of your
DC.
****
m_cfReportHeader.DeleteObject();
bFlag = m_cfReportHeader.CreatePointFontIndirect(&lfIniDefaults, &m_dc);
****
OK, you Are using CreatePointFontIndirect, so why all that other stuff which either
duplicates it or duplicates it badly?
****
pOldHeaderFont = m_dc.SelectObject(&m_cfReportHeader);
****
I have not saved an "old setting" on SelectObject in about 20 years. Use
SaveDC/RestoreDC. Otherwise, you get a lot of garbage variables and lose track of them
(there are over 30 DC parameters you might want to save the "old" version of!)
****
m_pcfReportHeader = &m_cfReportHeader;
*****
How in the world does this assigment make any sense whatsoever? It is complete nonsense.
Get rid of it.
****
// m_hFontReportHeader is the CGdiObject public data member that stores
the handle
m_hFontReportHeader = (HFONT) pOldHeaderFont->GetSafeHandle();
*****
This makes even less sense. Why do you need an HFONT anyway? There is something
seriously wrong hwere with what you are doing.
****
//m_hFontReportHeader = (HFONT) m_pcfReportHeader->GetSafeHandle();
/* Get Average size of printed text for the Header Font */
m_dc.GetTextMetrics(&myTextMetrics);
m_yLineHeader = myTextMetrics.tmHeight;
Later when I want to use the font in a report, I select the font, and do a
DrawText.
Here is a code snippet:
pcfOriginal =
ts->_this->PrinterControl.m_dc.SelectObject(ts->_this->PrinterControl.m_pcfReportHeader);