如何在指定矩形框内水平/垂直显示多行文字(修订)

类别:VC语言 点击:0 评论:0 推荐:

///////////////////////////////////////////////////////
// 说明(映射方式MM_LOMETRIC下):
//
//     在矩形框中水平或垂直显示多行文字
//
// 编写:
//     徐景周([email protected])
//
// 参数:
//       pDC: 绘制DC
//
//  szString: 绘制的字符串
//
//    lpRect: 绘制的矩形范围
//
//     lMode: 排列方式,0:水平方式; 1:垂直方式 
//
//     lHori: 水平对齐方式, 0:左对齐; 1:居中; 2:右对齐; 3:自定义
//
//     lVert: 垂直对齐方式, 0:顶对齐; 1:居中; 2:底对齐; 3:自定义
///////////////////////////////////////////////////////
CRect DrawTitleInRect(CDC *pDC, CString szString, LPRECT lpRect, long lMode, long lHori, long lVert)
{
 CRect rcInner(lpRect);

 if(rcInner.Width() ==0)
  return rcInner;

 TEXTMETRIC tm;
 pDC->GetTextMetrics(&tm);
 int tmpWidth=tm.tmAveCharWidth, tmpHeight=tm.tmHeight;

 //---------------------------------------------------------------------------------------------
 //功能:根据新、老矩形,重新计算行数,使文字多行显示,jingzhou xu
 //---------------------------------------------------------------------------------------------
 //一行中最大字符数
 int nMaxLineChar = abs(lpRect->right - lpRect->left) / tmpWidth; 
 if(nMaxLineChar < 2)               //应该至少能显示一个汉字
  return rcInner;

 //记录当前行的宽度
 short theLineLength=0; 
 //记录当前行中汉字字节数,以防止将一半汉字分为两行
 unsigned short halfChinese=0;

 for(int i=0; i<=szString.GetLength()-1; i++)
 {
  if(((unsigned char)szString.GetAt(i) == 0x0d) && ((unsigned char)szString.GetAt(i+1) == 0x0a))
   theLineLength=0;

  // 在此加入"||"字符为换行标志字符,输入时可根据此字符串来自动换行
  if(((unsigned char)szString.GetAt(i) == '|') && ((unsigned char)szString.GetAt(i+1) == '|'))
  {
   szString.SetAt(i,(unsigned char)0x0d);
   szString.SetAt(i+1,(unsigned char)0x0a);
  }

  //大于0xa1的字节为汉字字节
  if((unsigned char)szString.GetAt(i) >= 0xA1)
   halfChinese++;
  theLineLength++;

  //如果行宽大于每行最大宽度,进行特殊处理
  if(theLineLength > nMaxLineChar)
  {
   //防止将一个汉字分为两行,回溯
   if(!(halfChinese%2) && (unsigned char)szString.GetAt(i) >= 0xA1)
   {
    szString.Insert(i-1,(unsigned char)0x0a);
    szString.Insert(i-1,(unsigned char)0x0d);
    //注:此处不加一跳过,是由于它是在i-1处添加,只需跳到<i+1>处,故只需在循环处加一次既可。
   }
   else
   {
    szString.Insert(i,(unsigned char)0x0a);
    szString.Insert(i,(unsigned char)0x0d);

    i++;       //跳过新增的换行符,应跳到<i+2>处(循环中加一次,故这里只加一次)
   }
   
   theLineLength = 0;
   halfChinese=0;
  }
 }

 if(lMode==0)        //水平排列
 {
  rcInner.left+=tmpWidth;
  rcInner.right-=tmpWidth;
  rcInner.top-=tmpWidth;
  rcInner.bottom+=tmpWidth;
 }
 if(lMode==1)        //垂直排列
 {
  rcInner.left+=tmpWidth;
  rcInner.right=rcInner.left+tmpWidth;
  rcInner.top-=tmpWidth;
  rcInner.bottom+=tmpWidth;
 }

 //重新计算矩形边界范围
 pDC->DrawText(szString, rcInner,DT_WORDBREAK|DT_LEFT|DT_CALCRECT);

 switch(lHori)
 {
 case 0:
  break;
 case 1:
  {
   long xOutCent=(lpRect->right+lpRect->left)/2;
   long xInnCent=(rcInner.right+rcInner.left)/2;
   rcInner.left+=(xOutCent-xInnCent);
   rcInner.right+=(xOutCent-xInnCent);
  }
  break;
 case 2:
  {
   long lInWidth=rcInner.right-rcInner.left;
   rcInner.right=lpRect->right-tmpWidth;
   rcInner.left=rcInner.right-lInWidth;
  }
  break;
 default:
  break;
 }
 
 switch(lVert)
 {
 case 0:
  break;
 case 1:
  {
   long yOutCent=(lpRect->bottom+lpRect->top)/2;
   long yInnCent=(rcInner.bottom+rcInner.top)/2;
   rcInner.top-=(yInnCent-yOutCent);
   rcInner.bottom-=(yInnCent-yOutCent);
  }
  break;
 case 2:
  {
   long lInHeigh=rcInner.top-rcInner.bottom;
   rcInner.bottom=lpRect->bottom+tmpWidth;
   rcInner.top=rcInner.bottom+lInHeigh;
  }
  break;
 default:
  break;
 }

 if(rcInner.bottom < lpRect->bottom)
  rcInner.bottom = lpRect->bottom;
 if(rcInner.top > lpRect->top)
  rcInner.top = lpRect->top;

 //---------------------------------------------------------------------------------------------

 if(lHori==0)
  pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_LEFT);
 else if(lHori==1)
  pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_CENTER);
 else if(lHori==2)
  pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_RIGHT);

 return rcInner;
}

本文地址:http://com.8s8s.com/it/it2188.htm