网上一个关于支持打印的ListView类代码的一点改动

来源:互联网 发布:招聘美工图片 编辑:程序博客网 时间:2024/05/16 12:36

在该程序中,因为每次在预览后的打印是要重新填充那块“画布”的,

所以在private void EndPrint(object sender, PrintEventArgs e)处理中要重新初始化一些变量

整体代码如下(只对支持预览的改动,其他若有问题,请高手指点)

  1. /* -----------------------------------------------------------------------------------------
  2.  * 【文件名】: PrintListView.cs
  3.  * 【说  明】: 支持 ListView 的所见即所得的打印的类
  4.  *            1、整个打印的部分分为页首、正文、页尾三个部分;
  5.  *            2、正文部分打印 ListView 的 ColumnHeader 以及 ListView 的 Items,通过 PrintPageBody() 实现;
  6.  *            3、页首、页尾的打印自由定制,默认的行为是页首打印标题,页尾打印页码和时间,需要改变页首和
  7.  *            页尾的默认打印方式,可以对 PrintPageHeader() 和 PrintPageTail() 函数进行重写,并进行打印区域
  8.  *            的重新计算;
  9.  *            4、支持预览
  10.  *            5、支持打印设置,如:是否每页都打印标题,设置页首、正文、页尾的打印字体,等。
  11.  *            
  12.  * 【作  者】: sashow ( sashow @ 163.com )
  13.  * 【日  期】: 2005.05.10
  14.  * ----------------------------------------------------------------------------------------*/
  15. using System;
  16. using System.Drawing;
  17. using System.Collections;
  18. using System.ComponentModel;
  19. using System.Windows.Forms;
  20. using System.Data;
  21. using System.Drawing.Printing;
  22. namespace ForCustoms
  23. {
  24.     /// <summary>
  25.     /// ListView 的所见即所得的打印支持类。
  26.     /// </summary>
  27.     public class PrintListView : ListView
  28.     {
  29.         /// <summary>
  30.         /// 指示是否进行打印预览,默认值为 true
  31.         /// </summary>
  32.         private bool m_bIsPreview;
  33.         /// <summary>
  34.         /// 指示是否总是打印标题,默认值为 true
  35.         /// </summary>
  36.         private bool m_bIsAlwaysPrintHeader;
  37.         /// <summary>
  38.         /// 需要打印的页首字符串
  39.         /// </summary>
  40.         private string m_sPrintHeaderString;
  41.         /// <summary>
  42.         /// 页首字体
  43.         /// </summary>
  44.         private Font m_oHeaderFont;
  45.         /// <summary>
  46.         /// 正文字体
  47.         /// </summary>
  48.         private Font m_oBodyFont;
  49.         /// <summary>
  50.         /// 页尾字体
  51.         /// </summary>
  52.         private Font m_oTailFont;
  53.         /// <summary>
  54.         /// 正文部分的 ColumnHeader 字体,该字体为正文字体的加粗形式
  55.         /// </summary>
  56.         private Font m_oColumnHeaderFont;
  57.         /// <summary>
  58.         /// 打印文档
  59.         /// </summary>
  60.         private PrintDocument m_oPrintDoc;
  61.         /// <summary>
  62.         /// 行间距
  63.         /// </summary>
  64.         private int m_nLineSpace;
  65.         private int m_nFromPageSave;
  66.         private int m_nPrintWidth;            // 打印区域宽度
  67.         private int m_nPrintHeight;            // 打印区域长度
  68.         private int m_nPageCount;            // 打印页数
  69.         private int m_nCurPrintPage;         // 当前正在打印的页码
  70.         private int m_nTotalPage;            // 共有的页数
  71.         private int m_nFromPage;            // 用户选择的打印起始页
  72.         private int m_nCurPrintItem;         // 当前正在打印的元素
  73.         private Rectangle m_oHeaderRect;      // 打印页首的区域
  74.         private Rectangle m_oBodyRect;         // 打印正文的区域
  75.         private Rectangle m_oTailRect;         // 打印页尾的区域
  76.         private Brush defaultBrush;
  77.         private Pen defaultPen;
  78.         int listViewWidth;
  79.         /// <summary>
  80.         /// 设置或获取是否进行打印预览
  81.         /// </summary>
  82.         public bool IsPreview
  83.         {
  84.             get { return m_bIsPreview; }
  85.             set { m_bIsPreview = value; }
  86.         }
  87.         /// <summary>
  88.         /// 设置或获取是否总是打印标题
  89.         /// </summary>
  90.         public bool IsAlwaysPrintHeader
  91.         {
  92.             get { return m_bIsAlwaysPrintHeader; }
  93.             set { m_bIsAlwaysPrintHeader = value; }
  94.         }
  95.         /// <summary>
  96.         /// 设置或获取打印的页首字符串
  97.         /// </summary>
  98.         public string PrintHeaderString
  99.         {
  100.             get { return m_sPrintHeaderString; }
  101.             set { if (value != null) m_sPrintHeaderString = value; }
  102.         }
  103.         /// <summary>
  104.         /// 设置或获取页首字体
  105.         /// </summary>
  106.         public Font HeaderFont
  107.         {
  108.             set { m_oHeaderFont = value; }
  109.             get { return m_oHeaderFont; }
  110.         }
  111.         /// <summary>
  112.         /// 设置或获取正文字体
  113.         /// 如果对正文字体的 Bold 属性设置为 true ,则发生 Exception 类型的异常
  114.         /// </summary>
  115.         public Font BodyFont
  116.         {
  117.             set
  118.             {
  119.                 if (value == null)
  120.                     return;
  121.                 if (value.Bold == true)
  122.                 {
  123.                     throw new Exception("正文字体不能进行 [加粗] 设置.");
  124.                 }
  125.                 else
  126.                 {
  127.                     m_oBodyFont = value;
  128.                 }
  129.             }
  130.             get { return m_oBodyFont; }
  131.         }
  132.         /// <summary>
  133.         /// 设置或获取页尾字体
  134.         /// </summary>
  135.         public Font TailFont
  136.         {
  137.             set { m_oTailFont = value; }
  138.             get { return m_oTailFont; }
  139.         }
  140.         /// <summary>
  141.         /// 设置或获取行间距
  142.         /// </summary>
  143.         public int LineSpace
  144.         {
  145.             get { return m_nLineSpace; }
  146.             set
  147.             {
  148.                 if (value < 0)
  149.                 {
  150.                     m_nLineSpace = 0;
  151.                 }
  152.                 m_nLineSpace = value;
  153.             }
  154.         }
  155.         /// <summary>
  156.         /// 构造函数,设置打印信息的一些默认值
  157.         /// </summary>
  158.         public PrintListView()
  159.         {
  160.             m_bIsPreview = true;
  161.             m_bIsAlwaysPrintHeader = true;
  162.             m_sPrintHeaderString = "";
  163.             m_oHeaderFont = null;
  164.             m_oTailFont = null;
  165.             m_oBodyFont = null;
  166.             m_oColumnHeaderFont = null;
  167.             m_oPrintDoc = null;
  168.             m_nPrintWidth = 0;
  169.             m_nPrintHeight = 0;
  170.             m_nPageCount = 0;
  171.             m_nCurPrintPage = 1;
  172.             m_nFromPage = 1;
  173.             m_nLineSpace = 0;
  174.             m_nCurPrintItem = 0;
  175.             defaultBrush = Brushes.Black;
  176.             defaultPen = new Pen(defaultBrush, 1);
  177.         }
  178.         /// <summary>
  179.         /// 初始化打印文档的属性
  180.         /// </summary>
  181.         /// <returns></returns>
  182.         private void InitPrintDocument()
  183.         {
  184.             m_oPrintDoc = new PrintDocument();
  185.             m_oPrintDoc.DocumentName = m_sPrintHeaderString;
  186.             if (m_oPrintDoc.PrinterSettings.PrinterName == "<no default printer>")
  187.             {
  188.                 throw new Exception("未找到默认打印机.");
  189.             }
  190.             else
  191.             {
  192.                 m_oPrintDoc.PrintPage += new PrintPageEventHandler(PrintPage);
  193.                 m_oPrintDoc.BeginPrint += new PrintEventHandler(BeginPrint);
  194.                 m_oPrintDoc.EndPrint += new PrintEventHandler(EndPrint);
  195.             }
  196.             /* 设置打印字体 */
  197.             if (m_oHeaderFont == null)
  198.             {
  199.                 m_oHeaderFont = new Font("楷体_GB2312", 24, FontStyle.Bold, GraphicsUnit.World);
  200.             }
  201.             if (m_oBodyFont == null)
  202.             {
  203.                 m_oBodyFont = new Font("楷体_GB2312", 18, FontStyle.Regular, GraphicsUnit.World);
  204.             }
  205.             m_oColumnHeaderFont = new Font(m_oBodyFont, FontStyle.Bold);
  206.             if (m_oTailFont == null)
  207.             {
  208.                 m_oTailFont = new Font("楷体_GB2312", 12, FontStyle.Regular, GraphicsUnit.World);
  209.             }
  210.         }
  211.         /// <summary>
  212.         /// 初始化打印纸张设置
  213.         /// </summary>
  214.         private bool InitPrintPage(out Margins margins)
  215.         {
  216.             margins = null;
  217.             /* 获取当前 listview 的分辨率 */
  218.             Graphics g = this.CreateGraphics();
  219.             float x = g.DpiX;
  220.             g.Dispose();
  221.             /* 显示纸张设置对话框 */
  222.             PageSetupDialog ps = new PageSetupDialog();
  223.             ps.Document = m_oPrintDoc;
  224.             if (ps.ShowDialog() == DialogResult.Cancel)
  225.             {
  226.                 return false;
  227.             }
  228.             else
  229.             {               // 根据用户设置的纸张信息计算打印区域,计算结果的单位为 1/100 Inch
  230.                 m_nPrintWidth = ps.PageSettings.Bounds.Width - ps.PageSettings.Margins.Left - ps.PageSettings.Margins.Right;
  231.                 m_nPrintHeight = ps.PageSettings.Bounds.Height - ps.PageSettings.Margins.Top - ps.PageSettings.Margins.Bottom;
  232.                 margins = ps.PageSettings.Margins;
  233.             }
  234.             if (m_nPrintWidth <= 0 || m_nPrintHeight <= 0)
  235.             {
  236.                 throw new Exception("纸张设置错误.");
  237.             }
  238.             /* 将当前 listview 的各column的长度和转换为英寸,判断打印范围是否越界 */
  239.             listViewWidth = 0;
  240.             for (int i = 0; i < this.Columns.Count; i++)
  241.             {
  242.                 listViewWidth += this.Columns[i].Width;
  243.             }
  244.             if (Convert.ToInt32(listViewWidth / x * 100) > m_nPrintWidth)
  245.             {
  246.                 throw new Exception("打印内容超出纸张范围 !/r/n请尝试调整纸张或纸张边距;/r/n或缩小表格各列的宽度。");
  247.             }
  248.             m_oPrintDoc.DefaultPageSettings = ps.PageSettings;
  249.             return true;
  250.         }
  251.         /// <summary>
  252.         /// 初始化打印页码设置
  253.         /// </summary>
  254.         private bool InitPrintPageNumber(Margins margins)
  255.         {
  256.             /* 计算页数 */
  257.             int headerFontHeight = m_oHeaderFont.Height;
  258.             int columnHeaderFontHeight = m_oColumnHeaderFont.Height;
  259.             int bodyFontHeight = m_oBodyFont.Height;
  260.             int tailFontHeight = m_oTailFont.Height;
  261.             // 页首区域打印 页首字符串 以及一条横线
  262.             m_oHeaderRect = new Rectangle(margins.Left, margins.Top, m_nPrintWidth, headerFontHeight + m_nLineSpace + 3);
  263.             int tailHeight = tailFontHeight + m_nLineSpace + 3;
  264.             // 页尾区域打印 一条横线,页码和打印时间(在同一行)
  265.             m_oTailRect = new Rectangle(margins.Left, margins.Top + m_nPrintHeight - tailHeight, m_nPrintWidth, tailHeight);
  266.             //正文区域为去掉页首和页尾区域的部分
  267.             m_oBodyRect = new Rectangle(margins.Left + (m_nPrintWidth - listViewWidth) / 2, m_oHeaderRect.Bottom + 2, m_nPrintWidth, m_oTailRect.Top - m_oHeaderRect.Bottom - 4);
  268.             /* 计算第一页能打印的元素个数 */
  269.             int printItemPerPage = 0;
  270.             int firstPageItem = Convert.ToInt32((m_oBodyRect.Height - columnHeaderFontHeight - m_nLineSpace) / (bodyFontHeight + m_nLineSpace));
  271.             if (firstPageItem >= this.Items.Count)
  272.             {   // 需打印的元素只有一页
  273.                 m_nPageCount = 1;
  274.             }
  275.             else
  276.             {                              
  277.                 // 需要打印的元素有多页
  278.                 printItemPerPage = firstPageItem;
  279.                 int leftItems = this.Items.Count - firstPageItem;
  280.                 if (m_bIsAlwaysPrintHeader == false)
  281.                 {
  282.                     printItemPerPage = (m_oBodyRect.Height + m_oHeaderRect.Height + 2 - columnHeaderFontHeight - m_nLineSpace) / (bodyFontHeight + m_nLineSpace);
  283.                 }
  284.                 if (leftItems % printItemPerPage == 0)
  285.                 {
  286.                     m_nPageCount = leftItems / printItemPerPage + 1;
  287.                 }
  288.                 else
  289.                 {
  290.                     m_nPageCount = leftItems / printItemPerPage + 2;
  291.                 }
  292.             }
  293.             m_nTotalPage = m_nPageCount;
  294.             /* 显示打印对话框 */
  295.             PrintDialog pd = new PrintDialog();
  296.             pd.Document = m_oPrintDoc;
  297.             pd.PrinterSettings.MinimumPage = 1;
  298.             pd.PrinterSettings.MaximumPage = m_nPageCount;
  299.             pd.PrinterSettings.FromPage = 1;
  300.             pd.PrinterSettings.ToPage = m_nPageCount;
  301.             pd.AllowPrintToFile = false;      // 不设置打印到文件
  302.             if (m_nPageCount > 1)
  303.             {
  304.                 pd.AllowSelection = true;
  305.             }
  306.             else
  307.             {
  308.                 pd.AllowSelection = false;
  309.             }
  310.             pd.AllowSomePages = true;
  311.             if (pd.ShowDialog() == DialogResult.OK)
  312.             {
  313.                 m_nPageCount = pd.PrinterSettings.ToPage - pd.PrinterSettings.FromPage + 1;
  314.                 if (pd.PrinterSettings.FromPage > 1)
  315.                 {
  316.                     m_nCurPrintItem = firstPageItem + (pd.PrinterSettings.FromPage - 2) * printItemPerPage;
  317.                 }
  318.                 else
  319.                 {
  320.                     m_nCurPrintItem = 0;
  321.                 }
  322.                 m_nFromPage = pd.PrinterSettings.FromPage;
  323.                 m_nFromPageSave = m_nFromPage;
  324.                 m_oPrintDoc.DocumentName = m_nPageCount.ToString();
  325.                 m_oPrintDoc.PrinterSettings = pd.PrinterSettings;
  326.                 return true;
  327.             }
  328.             else
  329.             {
  330.                 return false;
  331.             }
  332.         }
  333.         /// <summary>
  334.         /// 启动 ListView 的打印工作
  335.         /// </summary>
  336.         public virtual void DoPrint()
  337.         {
  338.             if (this.Items.Count <= 0)
  339.             {
  340.                 throw new Exception("没有需要打印的元素.");
  341.             }
  342.             InitPrintDocument();
  343.             Margins margins = null;
  344.             if (InitPrintPage(out margins) == false)
  345.                 return;
  346.             if (InitPrintPageNumber(margins) == false)
  347.                 return;
  348.             if (m_bIsPreview == false)
  349.             {
  350.                 m_oPrintDoc.Print();
  351.             }
  352.             else
  353.             {
  354.                 PrintPreviewDialog pd = new PrintPreviewDialog();
  355.                 pd.Document = m_oPrintDoc;
  356.                 pd.PrintPreviewControl.Zoom = 1.0;
  357.                 pd.WindowState = FormWindowState.Maximized;
  358.                 pd.ShowInTaskbar = true;
  359.                 pd.ShowDialog();
  360.             }
  361.         }
  362.         /// <summary>
  363.         /// 打印页首
  364.         /// </summary>
  365.         /// <param name="g"></param>
  366.         protected virtual void PrintPageHeader(Graphics g)
  367.         {
  368.             RectangleF textRect = new RectangleF(m_oHeaderRect.X, m_oHeaderRect.Y, m_oHeaderRect.Width, m_oHeaderRect.Height - 3);
  369.             CenterText(g, m_sPrintHeaderString, m_oHeaderFont, defaultBrush, textRect);
  370.             g.DrawLine(defaultPen, m_oHeaderRect.X, m_oHeaderRect.Bottom - 2, m_oHeaderRect.Right, m_oHeaderRect.Bottom - 2);
  371.         }
  372.         /// <summary>
  373.         /// 打印正文
  374.         /// </summary>
  375.         /// <param name="g"></param>
  376.         protected virtual void PrintPageBody(Graphics g)
  377.         {
  378.             Rectangle textRect = m_oBodyRect;
  379.             if (m_bIsAlwaysPrintHeader == false && m_nCurPrintPage != 1)
  380.             {
  381.                 textRect = new Rectangle(m_oHeaderRect.X, m_oHeaderRect.Y, m_oHeaderRect.Width, m_oHeaderRect.Height + 2 + m_oBodyRect.Height);
  382.             }
  383.             /* 打印标题,也就是 columnHeader */
  384.             int columnHeaderFontHeight = m_oColumnHeaderFont.Height;
  385.             int bodyFontHeight = m_oBodyFont.Height;
  386.             Rectangle columnHeaderRect = new Rectangle(textRect.X, textRect.Y, textRect.Width, columnHeaderFontHeight + m_nLineSpace);
  387.             PrintColumnHeader(g, m_oColumnHeaderFont, defaultBrush, columnHeaderRect);
  388.             /* 打印元素 */
  389.             int itemHeight = bodyFontHeight + m_nLineSpace;
  390.             Rectangle itemRect;
  391.             int yPos = columnHeaderRect.Bottom;
  392.             int printItemPerPage = (textRect.Height - columnHeaderRect.Height) / (bodyFontHeight + m_nLineSpace);
  393.             for (int i = 0; (i < printItemPerPage) && (m_nCurPrintItem < this.Items.Count); i++)
  394.             {
  395.                 itemRect = new Rectangle(textRect.X, yPos, textRect.Width, itemHeight);
  396.                 PrintItem(g, m_oBodyFont, defaultBrush, itemRect);
  397.                 m_nCurPrintItem++;
  398.                 yPos += itemHeight;
  399.             }
  400.         }
  401.         /// <summary>
  402.         /// 打印页尾
  403.         /// </summary>
  404.         /// <param name="g"></param>
  405.         protected virtual void PrintPageTail(Graphics g)
  406.         {
  407.             g.DrawLine(defaultPen, m_oTailRect.X, m_oTailRect.Top + 1, m_oTailRect.Right, m_oTailRect.Top + 1);
  408.             RectangleF textRect = new RectangleF(m_oTailRect.X, m_oTailRect.Y + 3, m_oTailRect.Width, m_oTailRect.Height - 3);
  409.             string text = "第 " + m_nFromPage.ToString() + " 页  共 " + m_nTotalPage.ToString() + " 页";
  410.             m_nFromPage++;
  411.             CenterText(g, text, m_oTailFont, defaultBrush, textRect);
  412.             string time = "打印时间:" + DateTime.Now.ToLongDateString() + "   ";
  413.             RightText(g, time, m_oTailFont, defaultBrush, textRect);
  414.         }
  415.         /// <summary>
  416.         /// 打印一页
  417.         /// </summary>
  418.         /// <param name="sender"></param>
  419.         /// <param name="e"></param>
  420.         private void PrintPage(object sender, PrintPageEventArgs e)
  421.         {
  422.             e.Graphics.PageUnit = GraphicsUnit.Inch;
  423.             e.Graphics.PageScale = .01f;
  424.             if (m_bIsAlwaysPrintHeader == true)
  425.             {
  426.                 PrintPageHeader(e.Graphics);
  427.             }
  428.             else
  429.             {
  430.                 if (m_nCurPrintPage == 1)
  431.                 {
  432.                     PrintPageHeader(e.Graphics);
  433.                 }
  434.             }
  435.             PrintPageBody(e.Graphics);
  436.             PrintPageTail(e.Graphics);
  437.             if (m_nCurPrintPage == m_nPageCount)
  438.             {
  439.                 e.HasMorePages = false;
  440.             }
  441.             else
  442.             {
  443.                 e.HasMorePages = true;
  444.             }
  445.             m_nCurPrintPage++;
  446.         }
  447.         /// <summary>
  448.         /// 打印前的初始化设置
  449.         /// </summary>
  450.         /// <param name="sender"></param>
  451.         /// <param name="e"></param>
  452.         private void BeginPrint(object sender, PrintEventArgs e)
  453.         {
  454.             m_nCurPrintPage = 1;
  455.         }
  456.         /// <summary>
  457.         /// 打印结束后的资源释放
  458.         /// </summary>
  459.         /// <param name="sender"></param>
  460.         /// <param name="e"></param>
  461.         private void EndPrint(object sender, PrintEventArgs e)
  462.         {
  463.             m_nCurPrintItem = 0;
  464.             m_nFromPage = m_nFromPageSave;
  465.         }
  466.         /// <summary>
  467.         /// 居中显示文本信息
  468.         /// </summary>
  469.         private void CenterText(Graphics g, string t, Font f, Brush b, RectangleF rect)
  470.         {
  471.             StringFormat sf = new StringFormat();
  472.             sf.Alignment = StringAlignment.Center;
  473.             sf.LineAlignment = StringAlignment.Center;
  474.             g.DrawString(t, f, b, rect, sf);
  475.         }
  476.         /// <summary>
  477.         /// 居右显示文本信息
  478.         /// </summary>
  479.         private void RightText(Graphics g, string t, Font f, Brush b, RectangleF rect)
  480.         {
  481.             StringFormat sf = new StringFormat();
  482.             sf.Alignment = StringAlignment.Far;
  483.             sf.LineAlignment = StringAlignment.Center;
  484.             g.DrawString(t, f, b, rect, sf);
  485.         }
  486.         /// <summary>
  487.         /// 居左显示文本信息
  488.         /// </summary>
  489.         private void LeftText(Graphics g, string t, Font f, Brush b, RectangleF rect)
  490.         {
  491.             StringFormat sf = new StringFormat();
  492.             sf.Alignment = StringAlignment.Near;
  493.             sf.LineAlignment = StringAlignment.Center;
  494.             g.DrawString(t, f, b, rect, sf);
  495.         }
  496.         /// <summary>
  497.         /// 打印 listview 的 columnheader
  498.         /// </summary>
  499.         private void PrintColumnHeader(Graphics g, Font f, Brush b, Rectangle rect)
  500.         {
  501.             StringFormat sf = new StringFormat();
  502.             sf.Alignment = StringAlignment.Center;
  503.             sf.LineAlignment = StringAlignment.Center;
  504.             Rectangle itemRect;
  505.             Point location = new Point(rect.Location.X, rect.Location.Y);
  506.             Size itemSize;
  507.             for (int i = 0; i < this.Columns.Count; i++)
  508.             {
  509.                 itemSize = new Size(this.Columns[i].Width, rect.Height);
  510.                 itemRect = new Rectangle(location, itemSize);
  511.                 g.DrawRectangle(defaultPen, itemRect);
  512.                 g.DrawString(this.Columns[i].Text, f, b, itemRect, sf);
  513.                 location.X += this.Columns[i].Width;
  514.             }
  515.         }
  516.         /// <summary>
  517.         /// 打印 listview 的 item
  518.         /// </summary>
  519.         private void PrintItem(Graphics g, Font f, Brush b, Rectangle rect)
  520.         {
  521.             StringFormat sf = new StringFormat();
  522.             sf.Alignment = StringAlignment.Near;
  523.             sf.LineAlignment = StringAlignment.Center;
  524.             Rectangle itemRect;
  525.             Point location = new Point(rect.Location.X, rect.Location.Y);
  526.             Size itemSize;
  527.             for (int i = 0; i < this.Columns.Count; i++)
  528.             {
  529.                 itemSize = new Size(this.Columns[i].Width, rect.Height);
  530.                 itemRect = new Rectangle(location, itemSize);
  531.                 g.DrawRectangle(defaultPen, itemRect);
  532.                 g.DrawString(this.Items[m_nCurPrintItem].SubItems[i].Text, f, b, itemRect, sf);
  533.                 location.X += this.Columns[i].Width;
  534.             }
  535.         }
  536.     }
  537. }
最后感谢原著
原创粉丝点击