当前位置:编程学习 > VB >>

求救!打印预览方面的问题!懂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
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,