VC编写自动制表程序

       从一个文本文件中读出表头项目,表头按树型结构(多叉树)表示,然后编写带界面的ocx控件来显示表格,以供其它应用程序来调用。

1、  表头文本文件

上下边距: 10

左右边距: 10

字间距: 2

行间距: 10

字体: 宋体

字体大小: 10

对齐方式: 0

编号: 1   行数: 2 名称: 中国 北海 子项数: 2

编号: 1.1 行数: 2 名称: 旅顺 基地 子项数: 0

编号: 1.2 行数: 2 名称: 青岛 基地 子项数: 1

编号: 1.2.1 行数: 2 名称: 码头 海港 子项数: 0

编号: 2   行数: 1 名称: 第一集团  子项数: 2

编号: 2.1 行数: 1 名称: 第一纵队  子项数: 0

编号: 2.2 行数: 1 名称: 第二纵队  子项数: 0

编号: 3   行数: 2 名称: 中国 南海 子项数: 3

编号: 3.1 行数: 2 名称: 汕头 基地 子项数: 2

编号: 3.1.1 行数: 2 名称: 大海 海港 子项数: 1

编号: 3.1.1 .1 行数: 2 名称: 大海 海港 子项数: 0

编号: 3.1.2 行数: 2 名称: 山川 海港 子项数: 0

编号: 3.2 行数: 2 名称: 珠海 基地 子项数: 0

编号: 3.3 行数: 2 名称: 深圳 基地 子项数: 1

编号: 3.3.1 行数: 2 名称: 小平 海港 子项数: 0

编号: 4   行数: 3 名称: 中国 东海 第二 子项数: 0

编号: 5   行数: 1 名称: 第二集团 子项数: 3

编号: 5.1 行数: 1 名称: 第一队  子项数: 0

编号: 5.2 行数: 1 名称: 第二队  子项数: 1

编号: 5.2.1 行数: 1 名称: 山川海港 子项数: 1

编号: 5.2.1 .1 行数: 2 名称: 山川 海港 子项数: 1

编号: 5.2.1 .1.1 行数: 1 名称: 山川海港 子项数: 0

编号: 5.3 行数: 1 名称: *3纵队  子项数: 0

注:文件规则

l         父一定在子的前面

l         哥哥一定在弟弟的前面

l         父亲的宽度不能小于儿子的宽度和

l         如果在字符间有空格,请用*号代替

2、  生成的表格(见图)

3、  编写每个表格项的类

class CTableNode 

{

public:

       CTableNode();

       virtual ~CTableNode();

public:

       char*  sNo;                 //编号

       char*  sName;                    //名称

       unsigned short nLineNum;     //字符所占的行数

       unsigned short* nStartChar;  //根据行数而确定的起始字符位置数组

       unsigned short  nChildNum; //子项数

       unsigned short  nWidth;              //宽度

       unsigned short  nHeight;      //高度

       POINT pntStart;                  //起始点坐标

       unsigned short* nLevelNum; //分级的层次编号

       CTableNode* m_pParentNode;     //父结点

       void Draw(CDC* pDC, unsigned short left, unsigned short top, unsigned short bottom, int lineDis, int fontHeight, int textAlign);

};

void CTableNode::Draw(CDC* pDC,unsigned short left, unsigned short top, unsigned short bottom, int lineDis, int fontHeight, int textAlign)

{

       pDC->MoveTo(pntStart);

       pDC->LineTo(pntStart.x + nWidth, pntStart.y);

 

       pDC->MoveTo(pntStart);

       pDC->LineTo(pntStart.x, pntStart.y + nHeight);

 

       if(nChildNum == 0)

       {

              pDC->MoveTo(pntStart.x, pntStart.y + nHeight);

              pDC->LineTo(pntStart.x + nWidth, pntStart.y + nHeight);

 

              pDC->MoveTo(pntStart.x, pntStart.y + nHeight);

              pDC->LineTo(pntStart.x, bottom);

       }

       CString str;

       CString str1;

       str = sName;

       int iStart = 0;

       int iLineOffset = lineDis + fontHeight;

       for(int i = 0; i < nLineNum; i++)

       {

              if((i + 1) == nLineNum)

              {

                     str1 = str.Mid(iStart);

                     str1.Replace("*"," ");

                    

                    

              }

              else

              {

                     str1 = str.Mid(iStart, nStartChar[i] - iStart);

                     str1.Replace("*", " ");          

                     iStart = nStartChar[i];

              }

              int iY = (nHeight - (nLineNum*fontHeight + (nLineNum - 1)*lineDis))/2;

              iY = iY + pntStart.y;

              if(textAlign == 1)   //左对齐

                     pDC->TextOut(left + pntStart.x, iY + iLineOffset*i, str1); 

              else if(textAlign == 2)    //右对齐

              {

                     int iCharW = pDC->GetTextExtent(str1).cx;

                     pDC->TextOut(pntStart.x + nWidth - left - iCharW, iY + iLineOffset*i, str1);  

              }

              else  //居中

              {

                     int iCharW = pDC->GetTextExtent(str1).cx;      

                     pDC->TextOut(pntStart.x + (nWidth - iCharW)/2, iY + iLineOffset*i, str1);     

              }

       }

}

4、  读取文本文件,建立树型结构

       FILE* fl = fopen(sFile,"r");

       if(fl == NULL) return;

       char strBuf[256];

      

       CString strTmp;

       int   iData;

       bool  bAdded = false;  

       CTableNode* lpTableNode = NULL;

      

       while(!feof(fl))

       {

              fscanf(fl,"%s",strBuf);

              strTmp = strBuf;

             

              if(strTmp == "编号:")

              {

                     lpTableNode = new CTableNode();

                     fscanf(fl,"%s",strBuf);

                     lpTableNode->sNo = new char[strlen(strBuf) + 1];

                     strcpy(lpTableNode->sNo ,strBuf);

                    

                     fscanf(fl,"%s",&strBuf);       //行数

                     fscanf(fl,"%d",&iData);

                     lpTableNode->nLineNum = iData;

 

                     fscanf(fl,"%s",&strBuf);       //名称

                     lpTableNode->nStartChar = new unsigned short[iData - 1];

                     lpTableNode->sName = new char[100];

                     for(int j = 0; j < lpTableNode->nLineNum; j++)

                     {

                            fscanf(fl,"%s",&strBuf);

                            if(j == 0)

                                   strcpy(lpTableNode->sName, strBuf);

                            else

                            {

                                   lpTableNode->nStartChar[j - 1] = strlen(lpTableNode->sName);

                                   strcat(lpTableNode->sName, strBuf);

                            }

                     }

                    

                     fscanf(fl,"%s",&strBuf);

                     fscanf(fl, "%d", &iData);

                     lpTableNode->nChildNum = iData;

                     m_lstNodes.Add(lpTableNode);

                     continue;

              }

              if(strTmp=="上下边距:")

              {

                     fscanf(fl, "%d", &m_nUpDownDis);

                     continue;

              }

              if(strTmp=="左右边距:")

              {

                     fscanf(fl, "%d", &m_nLeftRightDis);

                     continue;

              }

              if(strTmp=="字体:")

              {

                     fscanf(fl, "%s", m_sFontName);

                     continue;

              }

              if(strTmp=="字体大小:")

              {

                     fscanf(fl, "%d", &m_nFontSize);

                     continue;

              }

              if(strTmp=="字间距:")

              {

                     fscanf(fl, "%d", &m_nFontDis);

                     continue;

              }

              if(strTmp=="行间距:")

              {

                     fscanf(fl, "%d", &m_nLineDis);

                     continue;

              }

              if(strTmp == "对齐方式:")

              {

                     fscanf(fl, "%d", &m_nTextAlign);

                     continue;

              }

       }

       fclose(fl);

       设置字体

       m_font.DeleteObject();

       m_font.CreatePointFont(m_nFontSize*10, m_sFontName);

       m_pMemDC->SelectObject(&m_font);

       TEXTMETRIC metri;

       m_pMemDC->GetTextMetrics(&metri);

       m_nFontHeight = metri.tmHeight;

       m_nFontWidth = metri.tmAveCharWidth;

       m_pMemDC->SetTextCharacterExtra(m_nFontDis);

5、  生成表格

CString str;
 int sNoLen = 0;
 bool bDepth = false;
 unsigned short nTreeDepth = 0;
 unsigned short nWidthByDepth[MAX_TREE_DEPTH];
 for(int i = 0; i < m_lstNodes.GetSize(); i++)
 {
  CTableNode* pTableNode = (CTableNode*)m_lstNodes.GetAt(i);
  sNoLen = strlen(pTableNode->sNo);
  int iDotNum = CalDotNum(pTableNode->sNo);
  pTableNode->nLevelNum = new unsigned short[iDotNum + 1];
  if(iDotNum > 0)
  {//确定父节点
   str = pTableNode->sNo;
   int ri = str.ReverseFind('.');
   str = str.Left(ri);
   pTableNode->m_pParentNode = FindParents(str);
   
   str = pTableNode->sNo;
   for(int m = 0; m < (iDotNum+1); m++)
   {
    int istart = str.Find('.');
    if(istart == -1)
    {
     pTableNode->nLevelNum[m] = atoi(str);
     break;
    }
    pTableNode->nLevelNum[m] = atoi(str.Left(istart));
    str = str.Mid(istart + 1);
   }
  }
  else
  {
   pTableNode->nLevelNum[0] = atoi(pTableNode->sNo);
  }
  //计算不同深度情况下的最大字符数
  bDepth = false;
  for(int j = 0; j < nTreeDepth; j++)
  {
   if((iDotNum + 1) <= nTreeDepth)
   {
    bDepth = true;
    break;
   }
  }
  if(!bDepth)
  {
   m_pDeepNode = pTableNode;
   nWidthByDepth[iDotNum] = pTableNode->nLineNum;
   nTreeDepth ++;
  }
  else if(pTableNode->nLineNum > nWidthByDepth[iDotNum])
   nWidthByDepth[iDotNum] = pTableNode->nLineNum;

 }
 
 //计算高度和没有孩子的节点的宽度
 for(i = 0; i < m_lstNodes.GetSize(); i++)
 {
  CTableNode* pTableNode = (CTableNode*)m_lstNodes.GetAt(i);
  sNoLen = strlen(pTableNode->sNo);
  int iDotNum = CalDotNum(pTableNode->sNo);
  pTableNode->nHeight = m_nUpDownDis*2 + m_nLineDis*(nWidthByDepth[iDotNum]-1) + nWidthByDepth[iDotNum]*m_nFontHeight;
  if(pTableNode->nChildNum != 0)
   continue;
  int nMaxCharNum = 0;
  if(pTableNode->nLineNum == 1)
  {
   nMaxCharNum = strlen(pTableNode->sName);
  }
  else
  {  
   int nStart = 0;
   for(int j = 0; j < pTableNode->nLineNum; j++)
   {
    CString str = pTableNode->sName;
    if((j+1) >= pTableNode->nLineNum)
    {
     str = str.Mid(nStart);
    }
    else
    {
     str = str.Mid(nStart,pTableNode->nStartChar[j]);
     nStart = pTableNode->nStartChar[j];
    }
    if(nMaxCharNum < str.GetLength())
    {
     nMaxCharNum = str.GetLength();
    }
   }
  }
  pTableNode->nWidth = m_nLeftRightDis*2 + m_nFontDis*(nMaxCharNum/2 - 1) + nMaxCharNum*m_nFontWidth;
 }
 //求有孩子的节点的宽度,倒序遍历
 for(i = m_lstNodes.GetSize() - 1; i >= 0; i--)
 {
  CTableNode* pTableNode = (CTableNode*)m_lstNodes.GetAt(i);
  if(pTableNode->m_pParentNode != NULL)
  {
   pTableNode->m_pParentNode->nWidth += pTableNode->nWidth;
  }
 }
 //计算起始坐标
 for(i = 0; i < m_lstNodes.GetSize(); i++)
 {
  CTableNode* pTableNode = (CTableNode*)m_lstNodes.GetAt(i);
  pTableNode->pntStart.x = CalNodesPosX(pTableNode);
  unsigned short nTmpHeight = 0;
  CalNodesPosY(pTableNode, nTmpHeight);
  pTableNode->pntStart.y = nTmpHeight;
 }
 //没有孩子的节点高度与最深节点对齐
 for(i = 0; i < m_lstNodes.GetSize(); i++)
 {
  CTableNode* pTableNode = (CTableNode*)m_lstNodes.GetAt(i);
  if(pTableNode->nChildNum == 0 && (strlen(pTableNode->sNo) != strlen(m_pDeepNode->sNo)))
  {
   if(pTableNode->m_pParentNode == NULL)
    pTableNode->nHeight = m_pDeepNode->pntStart.y + m_pDeepNode->nHeight;
   else
    pTableNode->nHeight = m_pDeepNode->pntStart.y + m_pDeepNode->nHeight - (pTableNode->m_pParentNode->pntStart.y + pTableNode->m_pParentNode->nHeight);
  }
 }

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值