求救!打印预览方面的问题!懂vc++ 和 vb 的大侠帮忙!!!
我只学过vb。最近老是被一个如何实现“所见即所得”方面的问题所困扰。同一字体、同一点值,在屏幕上显示的和在打印机上输出的有些出入,屏幕上显示的要更宽一些。在网上狂找资料,好不容易发现一篇,是用VC++写的,看不很懂,晕!!!请哪位高人帮忙解释一下,不胜感激!!!该文章网址如下:http://www.codeguru.com/cpp/w-p/printing/article.php/c5897
我已经复制在下:
People who have ever tried to implement WYSIWYG text output encountered the problem of how to draw text on different devices and in different resolutions in the same way -- especially if you implemented text formatting.
Here is an explanation how to implement WYSIWYG text output:
First of all, we have to retrieve the refernce font data:
// Allocate memory to store font cached data
*ppFontInfo=new CTLFontInfo();
// Retrieve OUTLINETEXTMETRIC structure size
UINT nSize=GetOutlineTextMetrics(hDC,0,NULL);
if(!nSize)
throw system_exception();
pTextMetrics=(OUTLINETEXTMETRIC*)new BYTE[nSize];
// Retrieve OUTLINETEXTMETRIC structure
if(!GetOutlineTextMetrics(hDC,nSize,pTextMetrics))
throw system_exception();
// Get reference dc
// The best solution is to use device context with
// the largest resolution
if(!m_hReferenceDC)
{
if(!CreateReferenceDC())
leave;
}
// Retrieve device resolution
// Note: if you use GetDeviceCaps(LOGPIXELSY) with
// display device context it will return 96 or 120
// (depends on yours display settings). We have
// to calculate display resolution using next formula:
// GetDeviceCaps(HORZRES)/GetDeviceCaps(HORZSIZE)*25.4.
// Where: 25.4 - mm per inch.
double nLogPixelsY=GetDisplayLogPixelsY( m_hReferenceDC,
m_bDisplay);
// Create reference font with height equal to EMSquare.
LOGFONT lReferenceFont=lFont;
lReferenceFont.lfHeight=-MulDiv(pTextMetrics->otmEMSquare,
nLogPixelsY,72);
HFONT hReferenceFont=CreateFontIndirect(&lReferenceFont);
if(!hReferenceFont)
throw system_exception();
if((hOldFont=
(HFONT)SelectObject(m_hReferenceDC,hReferenceFont))==NULL)
throw system_exception();
// Retrieve reference font's OUTLINETEXTMETRIC structure size
UINT nSize1=GetOutlineTextMetrics(m_hReferenceDC,0,NULL);
if(nSize!=nSize1)
{
delete pTextMetrics;
pTextMetrics=(OUTLINETEXTMETRIC*)new BYTE[nSize1];
}
// Retrieve reference font's OUTLINETEXTMETRIC structure
if(!GetOutlineTextMetrics(m_hReferenceDC,nSize1,pTextMetrics))
throw system_exception();
// Store text metrics inside cached object
// NOTE: We have to divide all metrics by nLogPixelsY to
// use them later with another device context
(*ppFontInfo)->FillInTextMetrics(pTextMetrics,nLogPixelsY);
// Retrieve characters widths
int nCharsCount=pTextMetrics->otmTextMetrics.tmLastChar-
pTextMetrics->otmTextMetrics.tmFirstChar+1;
int* pCharWidths=new int[nCharsCount];
if(!GetCharWidth(m_hReferenceDC,
pTextMetrics->otmTextMetrics.tmFirstChar,
pTextMetrics->otmTextMetrics.tmLastChar,
pCharWidths))
leave;
(*ppFontInfo)->FillInCharactersWidths(pCharWidths,nCharsCount,
pTextMetrics->otmTextMetrics.tmFirstChar,
nLogPixelsY);
// Retrieve kerning pairs
DWORD dwSize=GetKerningPairs(m_hReferenceDC,0,NULL);
if(dwSize)
{
pKerningPairs=
(KERNINGPAIR*)new BYTE[dwSize*sizeof(KERNINGPAIR)];
if(!GetKerningPairs(m_hReferenceDC,dwSize,pKerningPairs))
throw system_exception();
(*ppFontInfo)->FillInKerningPairs( pKerningPairs,
dwSize,
nLogPixelsY);
delete pKerningPairs;
pKerningPairs=NULL;
}
delete pTextMetrics;
pTextMetrics=NULL;
We have to calculate distances between letters using our current device context resolution.
TL_PAIR Pair(0,0);
long nCount=strlen(szText);
double fKerningValue=0.0;
double fCurrentWidth=0.0;
double fTotalWidth=0.0;
// This coefficient will be used to convert font
// height from EMSquare to required height
double fReferenceFont2LocalFont=m_fFontHeight/
(double)pFontInfo->m_TextMetrics.otmEMSquare;
double fLogPixelsY=GetDisplayLogPixelsY(hDC,bDisplay);
for(long i=0;i < nCount;i++)
{
// Do we need to correct distances between characters?
if(bPerformKerning)
{
if(i < nCount-1)
{
// Adjust kerning
Pair.m_nFirst=szText[i];
Pair.m_nSecond=szText[i+1];
fKerningValue=pFontInfo->m_KerningPairsArray[Pair];
}
else
fKerningValue=0.0;
}
// Make sure we don't use incorrect (zero-sized) characters...
_ASSERT(pFontInfo->m_CharactersWidthsArray[szText[i]]);
// Calculate local character width
fCurrentWidth=
pFontInfo->m_CharactersWidthsArray[szText[i]]+
fKerningValue;
fCurrentWidth*=
fLogPixelsY*fReferenceFont2LocalFont*fZoomFactor;
CharactersWidthsArray.push_back(fCurrentWidth);
fTotalWidth+=fCurrentWidth;
}
Now we can display our text on any devices we want using ExtTextOut function.
ExtTextOut(hDC,x,y,ETO_CLIPPED,
&Rect,
m_TextLines[i]->GetTextLine(),
m_TextLines[i]->GetTextLineLength(),
m_TextLines[i]->GetWidthsArray());
--------------------编程问答-------------------- "People who have ever tried to implement... "我就不翻译了,代码翻译翻译.//后的为VB代码
UINT nSize=GetOutlineTextMetrics(hDC,0,NULL); //Dim nSize As Long, nSize=GetOutlineTextMetrics(hDC,0,0)
if(!nSize) //If nSize<>0 Then
throw system_exception(); //On Error Resume Next
pTextMetrics=(OUTLINETEXTMETRIC*)new BYTE[nSize]; //Dim TextMetrics As OUTLINETEXTMETRIC
// Retrieve OUTLINETEXTMETRIC structure
if(!GetOutlineTextMetrics(hDC,nSize,pTextMetrics)) //如果函数调用成功
throw system_exception();
// Get reference dc
// The best solution is to use device context with
// the largest resolution
if(!m_hReferenceDC) //如果m_hReference不为0
{
if(!CreateReferenceDC()) //函数调用成功
leave;
}
// Retrieve device resolution
// Note: if you use GetDeviceCaps(LOGPIXELSY) with
// display device context it will return 96 or 120
// (depends on yours display settings). We have
// to calculate display resolution using next formula:
// GetDeviceCaps(HORZRES)/GetDeviceCaps(HORZSIZE)*25.4.
// Where: 25.4 - mm per inch.
double nLogPixelsY=GetDisplayLogPixelsY( m_hReferenceDC,
m_bDisplay);
// Create reference font with height equal to EMSquare.
LOGFONT lReferenceFont=lFont;
lReferenceFont.lfHeight=-MulDiv(pTextMetrics->otmEMSquare,
nLogPixelsY,72);
HFONT hReferenceFont=CreateFontIndirect(&lReferenceFont);
if(!hReferenceFont)
throw system_exception();
if((hOldFont=
(HFONT)SelectObject(m_hReferenceDC,hReferenceFont))==NULL)
throw system_exception();
// Retrieve reference font's OUTLINETEXTMETRIC structure size
UINT nSize1=GetOutlineTextMetrics(m_hReferenceDC,0,NULL);
if(nSize!=nSize1)
{
delete pTextMetrics;
pTextMetrics=(OUTLINETEXTMETRIC*)new BYTE[nSize1];
}
// Retrieve reference font's OUTLINETEXTMETRIC structure
if(!GetOutlineTextMetrics(m_hReferenceDC,nSize1,pTextMetrics))
throw system_exception();
// Store text metrics inside cached object
// NOTE: We have to divide all metrics by nLogPixelsY to
// use them later with another device context
(*ppFontInfo)->FillInTextMetrics(pTextMetrics,nLogPixelsY);
// Retrieve characters widths
int nCharsCount=pTextMetrics->otmTextMetrics.tmLastChar-
pTextMetrics->otmTextMetrics.tmFirstChar+1;
int* pCharWidths=new int[nCharsCount];
if(!GetCharWidth(m_hReferenceDC,
pTextMetrics->otmTextMetrics.tmFirstChar,
pTextMetrics->otmTextMetrics.tmLastChar,
pCharWidths))
leave;
(*ppFontInfo)->FillInCharactersWidths(pCharWidths,nCharsCount, //对ppXX取*后就是一个p
pTextMetrics->otmTextMetrics.tmFirstChar,
nLogPixelsY);
// Retrieve kerning pairs
DWORD dwSize=GetKerningPairs(m_hReferenceDC,0,NULL);
if(dwSize)
{
pKerningPairs=
(KERNINGPAIR*)new BYTE[dwSize*sizeof(KERNINGPAIR)];
if(!GetKerningPairs(m_hReferenceDC,dwSize,pKerningPairs))
throw system_exception();
(*ppFontInfo)->FillInKerningPairs( pKerningPairs,
dwSize,
nLogPixelsY);
delete pKerningPairs;
pKerningPairs=NULL;
}
delete pTextMetrics;
pTextMetrics=NULL;
We have to calculate distances between letters using our current device context resolution.
TL_PAIR Pair(0,0);
long nCount=strlen(szText);
double fKerningValue=0.0;
double fCurrentWidth=0.0;
double fTotalWidth=0.0;
// This coefficient will be used to convert font
// height from EMSquare to required height
double fReferenceFont2LocalFont=m_fFontHeight/
(double)pFontInfo->m_TextMetrics.otmEMSquare;
double fLogPixelsY=GetDisplayLogPixelsY(hDC,bDisplay);
for(long i=0;i < nCount;i++)
{
// Do we need to correct distances between characters?
if(bPerformKerning)
{
if(i < nCount-1)
{
// Adjust kerning
Pair.m_nFirst=szText[i];
Pair.m_nSecond=szText[i+1];
fKerningValue=pFontInfo->m_KerningPairsArray[Pair];
}
else
fKerningValue=0.0;
}
// Make sure we don't use incorrect (zero-sized) characters...
_ASSERT(pFontInfo->m_CharactersWidthsArray[szText[i]]);
// Calculate local character width
fCurrentWidth=
pFontInfo->m_CharactersWidthsArray[szText[i]]+
fKerningValue;
fCurrentWidth*=
fLogPixelsY*fReferenceFont2LocalFont*fZoomFactor;
CharactersWidthsArray.push_back(fCurrentWidth);
fTotalWidth+=fCurrentWidth;
}
Now we can display our text on any devices we want using ExtTextOut function.
ExtTextOut(hDC,x,y,ETO_CLIPPED,
&Rect,
m_TextLines[i]->GetTextLine(),
m_TextLines[i]->GetTextLineLength(),
m_TextLines[i]->GetWidthsArray());
--------------------编程问答-------------------- 谢谢Asanscape。虽然我还是没看很懂:)
我想再问一下,Getkerningpairs 在VB中如何使用啊?试着用了一下,老是不成功。
补充:VB , API