.Net中复杂打印的灵活方法

    技术2022-05-19  18

    .Net中复杂打印的灵活方法

     

           最近在用C#做一个关于水处理渗透系统设计的项目,其中需要打印复杂的分析报告(包括系统详细参数、概要图、各点水质分析、限制警告信息等)。很多内容都是根据具体的操作动态产生,所以在打印时就没有固定的模式和页面数量。而.Net的打印原理中,分页逻辑需要开发人员自己设计,对于这种比较复杂的情况,分页逻辑的实现就比较困难了。参考网上一些打印的方法,均不能灵活有较的解决问题,所以决定自己重新设计一种简单的打印模式。现将这一思路与大家共享,希望能给读者带来点启发。(注:本文不对.Net的基本打印原理进行,请初学者先了解基本原理再看本文思路)

     

           1、首先参考Word的页面形式,将打印内容分为“页眉区-主体区-页脚区”。其中页眉区和页脚区为固定模式,打印比较简单,只需每页重复调用相应打印函数即可。“主体区”是打印的重点,也是复杂之所在。区域大小固定后,报告内容要根据需要分成若干分页打印。打印逻辑的设计就是为了解决这个分页问题。

           2、在“主体区”中,又可参照Excel的形式,将内容看作是若干“行”的集合,而各“行”中又包含了若干“单元”。为了使这一形式能够表达各种复杂的报告形式,可以对“单元”赋于各种属性:Type“单元类型(文本/图片)”、Text“文本内容”、Width“单元宽度”、Font“文本字体”、TextAlign“文本对齐方式”、bPrintFrame“是否打印边框”等,可以根据需要完善属性。“行”属性:Height“行高”(为当前行中单元的最大高度)、CellSet“单元集”等。具体实现参考附录类。

    (说明:每单元、每行均为独立的个体,没有相互制约性,其实现方式全由开发人员根据具体需要初使化。如一空白行,则可定义一默认行包含一个空文本的默认单元,不打印边框,设置行高就可;而对于数据表格,则可将对应的行高,单元宽度设置相同,边框打印,设置对齐方式即可;又如一小段文本,可以作为一个仅包含单个“单元”的“行”,行高为文本的总高度,或者根据需要划分为几行表示。)

    举例原主体如下:

    -------------------------------------------------------------------------------------------------------------------------------------

     

    数据表       

      列1 列2 行1 XX XX.00 行2 XX XX.00 

                

    警告:XXXXX

    -------------------------------------------------------------------------------------------------------------------------------------

    转化为如下主体列表存储格式:

    -------------------------------------------------------------------------------------------------------------------------------------

     

    数据表   列1 列2 行1 XX XX.00 行2 XX XX.00   警告:XXXXX 

    -------------------------------------------------------------------------------------------------------------------------------------

           3、打印内容的列表初使(注意:这只是对将要打印内容的列表化初使,不是正在的打印过程,在打印中将调用此列表数据)。这是打印编程过程中的主要劳动量所在,根据具体的打印内容,进行相应的初使操作。应用“主体列表”打印的思想,在此处初使时,仅需要考虑单个“行”对象的内容,完全不用考虑打印逻辑中的“分页”问题。就像是在一个足够长的页面中进行打印,直接简化了打印逻辑的复杂部份,使编程过程思想明确。

           4、打印逻辑实现。用如下的代码简单说明:

    /// <summary>

    /// 打印报告的主体部份函数,返回false表示打印结束,返回true表示下一页

    /// </summary>

    /// <param name="g">打印对象</param>

    /// <param name="rect">区域大小</param>

    private bool printBody(ref Graphics g, Rectangle rect)

    {

         int posY = rect.Top;

         int posX = rect.Left;

     

         while( this.nCurrentLine < this.Lines.Count )                           // 当列表未打印完继续

         {

             if( posY + this.Lines[this.nCurrentLine].Height > rect.Bottom)       

    // 若当前行将超出正文打印范围,则别起一页

                  return true;

            

             for(int i=0; i<this.Lines[this.nCurrentLine].CellSet.Count; i++)     

    {

                   ……// 打印当前行过程,略

                  posX += this.Lines[this.nCurrentLine].CellSet[i].Width;      // X坐标移至下一单元框

             }

     

             posX = rect.Left;                                                // X坐标初使

             posY += this.Lines [this.nCurrentLine].Height;                   // Y坐标移至下一行

             this.nCurrentLine++;                                             // 当前打印行号++

         }

        

         return false;

    }

     

    /// <summary>

    /// 打印文档

    /// </summary>

    private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)

    {

         Graphics g = e.Graphics;

        

         this.printHeader(ref g, headerRectangle);                        // 打印页眉

         bool bMorePage =  this.printBody(ref g, bodyRectangle);           // 打印正文

         this.printFooter(ref g, footerRectangle);                        // 打印页脚

     

         if( bMorePage == true)                                              // 需分页

             this.nCurrentPage++;

         else                                                                  // 打印结束

         {

             this.nCurrentPage = 1;

             this.nCurrentLine = 0;

         }

     

         e.HasMorePages = bMorePage;

    }

     

    对象类设计代码:

         /// <summary>

         /// 打印中单元格类

         /// </summary>

         public class CPrintCell:ICloneable

         {

             private bool mvarbIsPicture;                       // 是否是图片单元格

             private bool mvarbPrintFrame;                      // 是否打印文本框

             private int mvarWidth;                             // 单元框宽度

             private string mvarAlign;                          // 对集方式(LEFT|RIGHT|CENTER)

             private Font mvarFontOfCell;                       // 单元文本字体

             private string mvarText;                           // 单元文本内容

             private string mvarPicAddress;                     // 或是图片,则存图片地址

              //赋值及函数部分略

         }

     

    /// <summary>

    /// 打印中的行内单元格集合类

    /// </summary>

    public class CPrintCellSet:CollectionBase,ICloneable

    {

         public CPrintCellSet()

         {

         }

     

         public CPrintCell this[int index]

         {

             get

             {

                  return (CPrintCell)List[index];

             }

             set

             {

                  List[index] = value;

             }

         }

     

         public void Add(CPrintCell printcell)

         {

             this.List.Add(printcell);

         }

     

         public int IndexOf(CPrintCell printcell)

         {

             return this.List.IndexOf(printcell);

         }

     

         public void Remove(CPrintCell printcell)

         {

             if( this.IndexOf(printcell) != -1 )

                  this.List.Remove(printcell);

         }

    }

     

         /// <summary>

         /// 打印中的单元行类

         /// </summary>

         public class CPrintLine:ICloneable

         {

             private int mvarHeight;                                               // 行高度

             private  CPrintCellSet mvarCellSet = new CPrintCellSet();             // 行内单元集

              //赋值及函数部分略

    }

     

         /// <summary>

         /// 打印中的行集合类

         /// </summary>

         public class CPrintLineSet:CollectionBase

         {

             public CPrintLineSet()

             {

             }

     

             public CPrintLine this[int index]

             {

                  get

                  {

                       return (CPrintLine)List[index];

                  }

                  set

                  {

                       List[index] = value;

                  }

             }

     

             public void Add(CPrintLine printline)

             {

                  this.List.Add(printline);

             }

     

             public int IndexOf(CPrintLine printline)

             {

                  return this.List.IndexOf(printline);

             }

     

             public void Remove(CPrintLine printline)

             {

                  if( this.IndexOf(printline) != -1 )

                       this.List.Remove(printline);

             }

    }

     

    本文仅为了提供一种适用于复杂打印的新思路,文中举例的对象类设计还不够完善,可以根据具体需要进行补充。希望能给大家带来点打印编程方面的帮助。

    本文来自博客,转载请标明出处:http://blog.csdn.net/wen8465/archive/2008/10/31/3193244.aspx


    最新回复(0)