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

来源:互联网 发布:白金数据 网盘 编辑:程序博客网 时间:2024/05/29 02:39

.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);

         }

}

 

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


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