网页WEB打印控件制作

CandyNext 发布于 2016/06/13 10:41
阅读 2K+
收藏 11

 在WEB系统中,打印的确是比较烦人的问题,如果我们能制作一个属于自己的自定义的打印插件,那么我们在后续自定义打印的时候能随心所欲的控制打印,这样的效果对于程序员来说是非常开心的一件事件,本文将自己开发编写的C# 制作的HTML打印插件分享出来,让有同样需求的朋友提供一个参考;此插件是基于Microsoft .NET Framework 2.0 开发的,缺点是每台客户端在安装插件时,必须要安装Microsoft .NET Framework 2.0 ;本插件能实现 页眉、页脚、表头、标题、表尾的分页打印;支持纸张类型、自动补充空行等功能;由于技术有限,肯定有很多不足的地方,请批评指正!

由于本打印插件是基于我们开发平台的报表基础来开发设计的,所以打印控件的原理:通过JS将页面表格数据生成固定格式的XML字符串(图片通过64base图片格式)传送给打印插件,有打印插件自主绘图生成打印页面。E_Print插件可以在WEB或WinForm中使用:

打印插件完整源码:E_Print.rar (包含插件源码、打包程序、winform调试DEMO)

预览效果

我们可以通过源码中的 EPrintTest.exe 打印Winform 实例 ,来执行示范,

通过WEB前端js 生成打印的TABLE的 RptData.xml格式 数据,在WINForm中直接使用

如果在网页中,通过JS 直接传给打印控件就OK

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Printing;
using System.Xml;
using System.Security;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Text.RegularExpressions;

namespace E_Print
{
    /// <summary>
    /// 打印控件
    /// 实现IObjectSafety接口
    /// 网页上所有所使用到的GUID  通过Guid工具生成的唯一编码
    /// 74D1ED1D-B1A7-4039-A060-6F544FBE99EC 编码以后不允许修改
    /// </summary>
    [Guid("74D1ED1D-B1A7-4039-A060-6F544FBE99EC"), ProgId("EReportPrint"), ComVisible(true)]
    public partial class PrintControl : UserControl, IObjectSafety
    {
        #region 私有变量

        #region 通用参数

        /// <summary>
        /// 缩放比例
        /// </summary>
        private float Zoom = 1;

        /// <summary>
        /// 网页高度 像素 px
        /// </summary>
        private float HtmlHeight = 0;

        /// <summary>
        /// 网页宽度 像素 px
        /// </summary>
        private float HtmlWidth = 0;

        /// <summary>
        /// 报表区域矩形
        /// </summary>
        private RectangleF TableRect = new RectangleF();

        /// <summary>
        /// 报表绘制实例
        /// </summary>
        private ReportDraw RptDraw = new ReportDraw();

        #endregion

        #region 页边距

        /// <summary>
        /// 左边距 
        /// 毫米 mm(一位小数)
        /// </summary>
        private float _marginLeft = 9.9f;

        /// <summary>
        /// 右边距
        /// </summary>
        private float _marginRight = 9.9f;

        /// <summary>
        /// 上边距
        /// </summary>
        private float _marginTop = 9.9f;

        /// <summary>
        /// 下边距
        /// </summary>
        private float _marginBottom = 9.9f;

        #endregion

        #region 版型方向

        /// <summary>
        /// 版型方向 Landscape: true 横向;false 纵向
        /// </summary>
        private bool _landscape = false;

        #endregion

        #region 纸型大小

        /// <summary>
        /// 纸张类型
        /// </summary>
        private string _paperName = "A4";

        /// <summary>
        /// 纸张宽度
        /// </summary>
        private int _paperWidth = 210;    // 毫米

        /// <summary>
        /// 纸张高度
        /// </summary>
        private int _paperHeight = 297;   // 毫米

        #endregion

        #region 打印参数

        /// <summary>
        /// 自适应纸张大小方法 
        /// null: 无
        /// row:   横向
        /// col:  纵向
        /// </summary>
        private string _zoomType = "null";

        /// <summary>
        /// 是否每页打印标题
        /// </summary>
        private bool _isTblTitleAllPage = false;

        /// <summary>
        /// 是否每页打印表头
        /// </summary>
        private bool _isTblHeadAllPage = false;

        /// <summary>
        /// 是否每页打印表尾
        /// </summary>
        private bool _isTblFootAllPage = false;

        /// <summary>
        /// 最后一页自动补行
        /// </summary>
        private bool _isAutoFillRow = false;

        /// <summary>
        /// 字符溢出是否换行缩小处理方式
        /// </summary>
        private bool _isOverFlow = false;

        /// <summary>
        /// 打印数据
        /// </summary>
        private string _dataXml = "";

        #endregion

        #region 页眉参数

        /// <summary>
        /// 页眉--绘制页眉
        /// </summary>
        private bool _headDraw = false;

        /// <summary>
        /// 页眉--高度 毫米
        /// 默认 10 刚好
        /// </summary>
        private float _headHeight = 10.0f;

        /// <summary>
        /// 页眉--左侧文字
        /// </summary>
        private string _headLeft = "";

        /// <summary>
        /// 页眉--中间文字
        /// </summary>
        private string _headCenter = "";

        /// <summary>
        /// 页眉--右侧文字
        /// </summary>
        private string _headRight = "";

        /// <summary>
        /// 页眉--字体名称
        /// </summary>
        private string _headFontName = "宋体";

        /// <summary>
        /// 页眉--字体大小
        /// </summary>
        private string _headFontSize = "9pt";

        /// <summary>
        /// 页眉--字体颜色
        /// </summary>
        private string _headFontColor = "Black";

        /// <summary>
        /// 页眉--字体--粗体
        /// </summary>
        private bool _headFontBold = false;

        /// <summary>
        /// 页眉--字体--斜体
        /// </summary>
        private bool _headFontItalic = false;

        /// <summary>
        /// 页眉--字体--删除线
        /// </summary>
        private bool _headFontStrikeout = false;

        /// <summary>
        /// 页眉--字体--下划线
        /// </summary>
        private bool _headFontUnderline = false;

        /// <summary>
        /// 页眉--绘制分隔线
        /// </summary>
        private bool _headLineDraw = false;

        /// <summary>
        /// 页眉--分隔线宽度
        /// </summary>
        private float _headLineWidth = 1.0f;

        /// <summary>
        /// 页眉--分隔线线型
        /// </summary>
        private string _headLineDash = "solid";

        /// <summary>
        /// 页眉--分隔线颜色
        /// </summary>
        private string _headLineColor = "Black";

        #endregion

        #region 页脚参数

        /// <summary>
        /// 页脚--绘制页脚
        /// </summary>
        private bool _footDraw = false;

        /// <summary>
        /// 页脚--高度 毫米
        /// </summary>
        private float _footHeight = 10.0f;

        /// <summary>
        /// 页脚--左侧文字
        /// </summary>
        private string _footLeft = "";

        /// <summary>
        /// 页脚--中间文字
        /// </summary>
        private string _footCenter = "";

        /// <summary>
        /// 页脚--右侧文字
        /// </summary>
        private string _footRight = "";

        /// <summary>
        /// 页脚--字体名称
        /// </summary>
        private string _footFontName = "宋体";

        /// <summary>
        /// 页脚--字体大小
        /// </summary>
        private string _footFontSize = "9pt";

        /// <summary>
        /// 页脚--字体颜色
        /// </summary>
        private string _footFontColor = "Black";

        /// <summary>
        /// 页脚--字体--粗体
        /// </summary>
        private bool _footFontBold = false;

        /// <summary>
        /// 页脚--字体--斜体
        /// </summary>
        private bool _footFontItalic = false;

        /// <summary>
        /// 页脚--字体--删除线
        /// </summary>
        private bool _footFontStrikeout = false;

        /// <summary>
        /// 页脚--字体--下划线
        /// </summary>
        private bool _footFontUnderline = false;

        /// <summary>
        /// 页脚--绘制分隔线
        /// </summary>
        private bool _footLineDraw = false;

        /// <summary>
        /// 页脚--分隔线宽度
        /// </summary>
        private float _footLineWidth = 1.0f;

        /// <summary>
        /// 页脚--分隔线线型
        /// </summary>
        private string _footLineDash = "solid";

        /// <summary>
        /// 页脚--分隔线颜色
        /// </summary>
        private string _footLineColor = "Black";

        #endregion

        #endregion

        #region 构造方法

        /// <summary>
        /// 打印控件构造函数
        /// </summary>
        public PrintControl()
        {
            InitializeComponent();
            Init_PageSetting();
        }

        #endregion

        #region 接口实现

        private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
        private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
        private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
        private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
        private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";

        private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
        private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
        private const int S_OK = 0;
        private const int E_FAIL = unchecked((int)0x80004005);
        private const int E_NOINTERFACE = unchecked((int)0x80004002);

        private bool _fSafeForScripting = true;
        private bool _fSafeForInitializing = true;

        public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
        {
            int Rslt = E_FAIL;

            string strGUID = riid.ToString("B");
            pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
            switch (strGUID)
            {
                case _IID_IDispatch:
                case _IID_IDispatchEx:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForScripting == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistPropertyBag:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForInitializing == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }

            return Rslt;
        }

        public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
        {
            int Rslt = E_FAIL;
            string strGUID = riid.ToString("B");
            switch (strGUID)
            {
                case _IID_IDispatch:
                case _IID_IDispatchEx:
                    if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
                        Rslt = S_OK;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistPropertyBag:
                    if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
                        Rslt = S_OK;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }

            return Rslt;
        }

        #endregion

        #region 属性方法

        #region 页边距

        /// <summary>
        /// 获取--设置--左边距
        /// 计量单位 毫米(mm)
        /// </summary>
        public float MARGINLEFT
        {
            get { return _marginLeft; }
            set { _marginLeft = value; }
        }

        /// <summary>
        /// 获取--设置--右边距
        /// 计量单位 毫米(mm)
        /// </summary>
        public float MARGINRIGHT
        {
            get { return _marginRight; }
            set { _marginRight = value; }
        }

        /// <summary>
        /// 获取--设置--上边距
        /// 计量单位 毫米(mm) 
        /// </summary>
        public float MARGINTOP
        {
            get { return _marginTop; }
            set { _marginTop = value; }
        }

        /// <summary>
        /// 获取--设置--下边距
        /// 计量单位 毫米(mm) 
        /// </summary>
        public float MARGINBOTTOM
        {
            get { return _marginBottom; }
            set { _marginBottom = value; }
        }

        #endregion

        #region 版型方向

        /// <summary>
        /// 获取--设置--版型方向
        /// Landscape: true 横向; false 纵向
        /// </summary>
        public bool LANDSCAPE
        {
            get { return _landscape; }
            set { _landscape = value; }
        }

        #endregion

        #region 纸张属性

        /// <summary>
        /// 获取--设置--纸张类型
        /// </summary>
        public string PAPERNAME
        {
            get { return _paperName; }
            set { _paperName = value; }
        }

        /// <summary>
        /// 获取--设置--纸张高度
        /// 计量单位 毫米(mm)
        /// </summary>
        public int PAPERHEIGHT
        {
            get { return _paperHeight; }
            set { _paperHeight = value; }
        }

        /// <summary>
        /// 获取--设置--纸张宽度
        /// 计量单位 毫米(mm)
        /// </summary>
        public int PAPERWIDTH
        {
            get { return _paperWidth; }
            set { _paperWidth = value; }
        }

        #endregion

        #region 页眉参数

        /// <summary>
        /// 获取--设置--页眉是否绘制
        /// </summary>
        public bool HEADDRAW
        {
            get { return _headDraw; }
            set { _headDraw = value; }
        }

        /// <summary>
        /// 获取--设置--页眉高度
        /// 单位:毫米整数类型
        /// </summary>
        public float HEADHEIGHT
        {
            get { return _headHeight; }
            set { _headHeight = value; }
        }

        /// <summary>
        /// 获取--设置--页眉左侧文字
        /// </summary>
        public string HEADLEFT
        {
            get { return _headLeft; }
            set { _headLeft = value; }
        }

        /// <summary>
        /// 获取--设置--页眉中间文字
        /// </summary>
        public string HEADCENTER
        {
            get { return _headCenter; }
            set { _headCenter = value; }
        }

        /// <summary>
        /// 获取--设置--页眉右侧文字
        /// </summary>
        public string HEADRIGHT
        {
            get { return _headRight; }
            set { _headRight = value; }
        }

        /// <summary>
        /// 获取--设置--页眉字体名称
        /// </summary>
        public string HEADFONTNAME
        {
            get { return _headFontName; }
            set { _headFontName = value; }
        }

        /// <summary>
        /// 获取--设置--页眉字体大小
        /// </summary>
        public string HEADFONTSIZE
        {
            get { return _headFontSize; }
            set { _headFontSize = value; }
        }

        /// <summary>
        /// 获取--设置--页眉字体颜色
        /// </summary>
        public string HEADFONTCOLOR
        {
            get { return _headFontColor; }
            set { _headFontColor = value; }
        }

        /// <summary>
        /// 获取--设置--页眉字体--粗体
        /// </summary>
        public bool HEADFONTBOLD
        {
            get { return _headFontBold; }
            set { _headFontBold = value; }
        }

        /// <summary>
        /// 获取--设置--页眉字体--斜体
        /// </summary>
        public bool HEADFONTITALIC
        {
            get { return _headFontItalic; }
            set { _headFontItalic = value; }
        }

        /// <summary>
        /// 获取--设置--页眉字体--删除线
        /// </summary>
        public bool HEADFONTSTRIKEOUT
        {
            get { return _headFontStrikeout; }
            set { _headFontStrikeout = value; }
        }

        /// <summary>
        /// 获取--设置--页眉字体--下划线
        /// </summary>
        public bool HEADFONTUNDERLINE
        {
            get { return _headFontUnderline; }
            set { _headFontUnderline = value; }
        }

        /// <summary>
        /// 获取--设置--是否绘制分割线
        /// </summary>
        public bool HEADLINEDRAW
        {
            get { return _headLineDraw; }
            set { _headLineDraw = value; }
        }

        /// <summary>
        /// 获取--设置--页眉分隔线宽度
        /// </summary>
        public float HEADLINEWIDTH
        {
            get { return _headLineWidth; }
            set { _headLineWidth = value; }
        }

        /// <summary>
        /// 获取--设置--页眉分隔线线型
        /// </summary>
        public string HEADLINEDASH
        {
            get { return _headLineDash; }
            set { _headLineDash = value; }
        }

        /// <summary>
        /// 获取--设置--页眉分隔线颜色
        /// </summary>
        public string HEADLINECOLOR
        {
            get { return _headLineColor; }
            set { _headLineColor = value; }
        }

        #endregion

        #region 页脚参数

        /// <summary>
        /// 获取--设置--页脚是否绘制
        /// </summary>
        public bool FOOTDRAW
        {
            get { return _footDraw; }
            set { _footDraw = value; }
        }

        /// <summary>
        /// 获取--设置--页脚高度
        /// 单位:毫米整数类型
        /// </summary>
        public float FOOTHEIGHT
        {
            get { return _footHeight; }
            set { _footHeight = value; }
        }

        /// <summary>
        /// 获取--设置--页脚左侧文字
        /// </summary>
        public string FOOTLEFT
        {
            get { return _footLeft; }
            set { _footLeft = value; }
        }

        /// <summary>
        /// 获取--设置--页脚中间文字
        /// </summary>
        public string FOOTCENTER
        {
            get { return _footCenter; }
            set { _footCenter = value; }
        }

        /// <summary>
        /// 获取--设置--页脚右侧文字
        /// </summary>
        public string FOOTRIGHT
        {
            get { return _footRight; }
            set { _footRight = value; }
        }

        /// <summary>
        /// 获取--设置--页脚字体名称
        /// </summary>
        public string FOOTFONTNAME
        {
            get { return _footFontName; }
            set { _footFontName = value; }
        }

        /// <summary>
        /// 获取--设置--页脚字体大小
        /// </summary>
        public string FOOTFONTSIZE
        {
            get { return _footFontSize; }
            set { _footFontSize = value; }
        }

        /// <summary>
        /// 获取--设置--页脚字体颜色
        /// </summary>
        public string FOOTFONTCOLOR
        {
            get { return _footFontColor; }
            set { _footFontColor = value; }
        }

        /// <summary>
        /// 获取--设置--页脚字体--粗体
        /// </summary>
        public bool FOOTFONTBOLD
        {
            get { return _footFontBold; }
            set { _footFontBold = value; }
        }

        /// <summary>
        /// 获取--设置--页脚字体--斜体
        /// </summary>
        public bool FOOTFONTITALIC
        {
            get { return _footFontItalic; }
            set { _footFontItalic = value; }
        }

        /// <summary>
        /// 获取--设置--页脚字体--删除线
        /// </summary>
        public bool FOOTFONTSTRIKEOUT
        {
            get { return _footFontStrikeout; }
            set { _footFontStrikeout = value; }
        }

        /// <summary>
        /// 获取--设置--页脚字体--下划线
        /// </summary>
        public bool FOOTFONTUNDERLINE
        {
            get { return _footFontUnderline; }
            set { _footFontUnderline = value; }
        }

        /// <summary>
        /// 获取--设置--是否绘制分割线
        /// </summary>
        public bool FOOTLINEDRAW
        {
            get { return _footLineDraw; }
            set { _footLineDraw = value; }
        }

        /// <summary>
        /// 获取--设置--页脚分隔线宽度
        /// </summary>
        public float FOOTLINEWIDTH
        {
            get { return _footLineWidth; }
            set { _footLineWidth = value; }
        }

        /// <summary>
        /// 获取--设置--页脚分隔线线型
        /// </summary>
        public string FOOTLINEDASH
        {
            get { return _footLineDash; }
            set { _footLineDash = value; }
        }

        /// <summary>
        /// 获取--设置--页脚分隔线颜色
        /// </summary>
        public string FOOTLINECOLOR
        {
            get { return _footLineColor; }
            set { _footLineColor = value; }
        }

        #endregion

        #region 打印参数

        /// <summary>
        /// 获取--设置--打印数据
        /// 前台传入的XML格式的打印数据
        /// </summary>
        public string DATAXML
        {
            get { return _dataXml; }
            set { _dataXml = value; }
        }

        /// <summary>
        /// 获取--设置--是否每页打印标题
        /// </summary>
        public bool ISTBLTITLEALLPAGE
        {
            get { return _isTblTitleAllPage; }
            set { _isTblTitleAllPage = value; }
        }

        /// <summary>
        /// 获取--设置--是否每页打印表头
        /// </summary>
        public bool ISTBLHEADALLPAGE
        {
            get { return _isTblHeadAllPage; }
            set { _isTblHeadAllPage = value; }
        }

        /// <summary>
        /// 获取--设置--是否每页打印表尾
        /// </summary>
        public bool ISTBLFOOTALLPAGE
        {
            get { return _isTblFootAllPage; }
            set { _isTblFootAllPage = value; }
        }

        /// <summary>
        /// 获取--设置--末页自动补行
        /// </summary>
        public bool ISAUTOFILLROW
        {
            get { return _isAutoFillRow; }
            set { _isAutoFillRow = value; }
        }

        /// <summary>
        /// 获取--设置--缩放方向
        /// 参数:以下三种;默认null
        /// null: 无
        /// row:   横向
        /// col:  纵向
        /// </summary>
        public string ZOOMTYPE
        {
            get { return _zoomType; }
            set { _zoomType = value; }
        }

        /// <summary>
        /// 获取--设置--字符溢出是否缩小换行处理方式
        /// </summary>
        public bool ISOVERFLOW
        {
            get { return _isOverFlow; }
            set { _isOverFlow = value; }
        }

        #endregion

        #region 加载参数

        /// <summary>
        /// 加载打印参数
        /// </summary>
        public void INITPRINTPARAM()
        {
            Init_PageSetting();
        }

        #endregion

        #endregion

        #region 加载事件

        /// <summary>
        /// 初始化--页面设置参数
        /// </summary>
        private void Init_PageSetting()
        {
            this.E_PrintDocument.DefaultPageSettings.Margins.Left = (int)Math.Round(MARGINLEFT * 10);     // 左边距
            this.E_PrintDocument.DefaultPageSettings.Margins.Right = (int)Math.Round(MARGINRIGHT * 10);   // 右边距
            this.E_PrintDocument.DefaultPageSettings.Margins.Top = (int)Math.Round(MARGINTOP * 10);       // 上边距
            this.E_PrintDocument.DefaultPageSettings.Margins.Bottom = (int)Math.Round(MARGINBOTTOM * 10); // 下边距

            this.E_PrintDocument.PrinterSettings.Copies = 1;                                               // 打印份数
            this.E_PrintDocument.DefaultPageSettings.Landscape = this.LANDSCAPE;                           // 版型方向      
            PaperSize size = GetPaperSize(PAPERNAME);                                                      // 纸张类型
            if (size != null)
                this.E_PrintDocument.DefaultPageSettings.PaperSize = size;
            else
                this.E_PrintDocument.DefaultPageSettings.PaperSize = new PaperSize(this.PAPERNAME, (int)Math.Round(this.PAPERWIDTH / 25.4 * 100), (int)Math.Round(this.PAPERHEIGHT / 25.4 * 100));
        }

        /// <summary>
        /// 获取--纸张类型
        /// </summary>
        /// <param name="paperName">纸张类型名称</param>
        /// <returns></returns>
        private PaperSize GetPaperSize(string paperName)
        {
            PaperSize paper = null;
            foreach (PaperSize ps in this.E_PrintDocument.PrinterSettings.PaperSizes)
            {
                if (ps.PaperName.ToLower() == paperName.ToLower()) // 检查打印机是否有指定的纸张类型
                {
                    paper = ps;
                    break;
                }
            }
            return paper;
        }

        #endregion

        #region 打印事件

        /// <summary>
        /// 直接打印
        /// 此处加入了再次调用打印设置界面,因为用户可能需要选择那种打印机
        /// </summary>
        /// <returns></returns>
        public string PRINT()
        {
            // 直接打印时,直接调用printDocument的Print()方法
            // 因为用户可能在打印之前还要再更改打印设置所以需再次显示打印设置对话框
            if (this.E_PrintDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    this.Init_Printer();
                    this.E_PrintDocument.Print();
                }
                catch (Exception ex)
                {
                    this.E_PrintDocument.PrintController.OnEndPrint(this.E_PrintDocument, new PrintEventArgs());
                    return ex.Message.ToString();
                }
            }
            return "";
        }

        /// <summary>
        /// 打印预览
        /// 将打印的数据进行预览
        /// </summary>
        public string PREVIEW()
        {
            try
            {
                this.Init_Printer();
                this.E_PrintPreviewDialog.ShowDialog();
            }
            catch (Exception ex)
            {
                return ex.Message.ToString();
            }

            return "";
        }

        /// <summary>
        /// 页面设置
        /// 设置打印的页面的纸张大小、纸型、页面边距
        /// </summary>
        public void PAGESTE()
        {
            // 页面设置对话框中使用的是公制长度计量单位 (厘米)
            // 在.net中采用的是英制的计量单位 (英寸)
            // 1英寸约等于2.54厘米,1厘米=10毫米
            // 所以在下面中需要加入转换信息 将对话框中设置的页边距进行转换保存
            // 设置传入的纸张信息
            if (this.E_PageSetupDialog.ShowDialog() == DialogResult.OK)                          // 弹出页面设置对话框
            {
                if (System.Globalization.RegionInfo.CurrentRegion.IsMetric)                      // 转换页边距计量单位
                    this.E_PageSetupDialog.PageSettings.Margins = PrinterUnitConvert.Convert(this.E_PageSetupDialog.PageSettings.Margins, PrinterUnit.Display, PrinterUnit.TenthsOfAMillimeter);
                this.E_PrintDocument.DefaultPageSettings = this.E_PageSetupDialog.PageSettings;  // 更新页面设置参数值

                // 更新参数
                this.LANDSCAPE = this.E_PrintDocument.DefaultPageSettings.Landscape;                           // 版型方向  
                this.PAPERNAME = this.E_PrintDocument.DefaultPageSettings.PaperSize.PaperName;                 // 纸张类型
                PaperSize tmPSize = this.E_PrintDocument.DefaultPageSettings.PaperSize;                        // 纸张尺寸
                this.PAPERWIDTH = (int)Math.Round(tmPSize.Width * 25.4 / 100);                                 // 纸张宽度
                this.PAPERHEIGHT = (int)Math.Round(tmPSize.Height * 25.4 / 100);                               // 纸张高度
                this.MARGINLEFT = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Left / 10f, 1);     // 左边距
                this.MARGINRIGHT = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Right / 10f, 1);   // 右边距
                this.MARGINTOP = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Top / 10f, 1);       // 上边距
                this.MARGINBOTTOM = (float)Math.Round(this.E_PrintDocument.DefaultPageSettings.Margins.Bottom / 10f, 1); // 下边距
            }
        }

        /// <summary>
        /// 打印设置
        /// 设置打印机的信息(选择打印机、设置打印份数等信息)
        /// </summary>
        public void PRINTSET()
        {
            this.E_PrintDialog.ShowDialog();
        }

        #endregion

        #region 绘制对象

        /// <summary>
        /// 打印及打印前初始化数据
        /// </summary>
        private void Init_Printer()
        {
            HtmlHeight = 0;                                      // 网页报表高度
            HtmlWidth = 0;                                       // 网页报表宽度
            CalcTableRect();                                     // 计算区域矩形
            RptDraw = new ReportDraw();                          // 报表绘制实例
            RptDraw.IsAllPrintTitle = this._isTblTitleAllPage;   // 每页打印标题
            RptDraw.IsAllPrintHead = this._isTblHeadAllPage;     // 每页打印表头
            RptDraw.IsAllPrintFoot = this._isTblFootAllPage;     // 每页打印表尾
            RptDraw.IsAutoFillRow = this._isAutoFillRow;         // 末页自动补行
            RptDraw.IsOverFlow = this._isOverFlow;               // 字符溢出缩小
            RptDraw.ReptRect = TableRect;                        // 赋值报表矩形
            if (!ParseXML()) return;                             // 解析报表数据
            CalcReportZoom();                                    // 计算缩小比例
            CalcZoomAllSize();                                   // 按比计算尺寸
            RptDraw.Zoom = this.Zoom;                            // 赋值缩小比例         
            RptDraw.CalcPaging();                                // 计算打印分页
        }

        /// <summary>
        /// PrintDocument 对象打印绘制事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void E_PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
        {
            Graphics g = e.Graphics;
            g.Clear(Color.White);
            DrawHeader(g);
            DrawFooter(g);
            if (RptDraw.DrawReport(g))
                e.HasMorePages = true;
            else
                e.HasMorePages = false;

        }

        /// <summary>
        /// 绘制页眉
        /// </summary>
        /// <param name="g">绘图对象</param>
        private void DrawHeader(Graphics g)
        {
            // 是否绘制
            if (_headDraw)
            {
                // 页眉实例
                PageHeader pgHeader = new PageHeader();

                // 页眉矩形
                RectangleF pgHeaderRect = new RectangleF(TableRect.X,                          // X 坐标
                                                         TableRect.Y - mmToPixel(_headHeight), // Y 坐标      
                                                         TableRect.Width,                      // W 宽度
                                                         mmToPixel(_headHeight)                // H 高度
                                                         );

                // 页眉赋值
                pgHeader.HeadRect = pgHeaderRect;
                pgHeader.StrLeft = ReplacePageNum(_headLeft);     // 左侧文本
                pgHeader.StrCenter = ReplacePageNum(_headCenter); // 中间文本 
                pgHeader.StrRight = ReplacePageNum(_headRight);   // 右侧文本
                FontStyle fontStyle = FontStyle.Regular;          // 字体样式
                if (_headFontBold) fontStyle |= FontStyle.Bold;
                if (_headFontItalic) fontStyle |= FontStyle.Italic;
                if (_headFontStrikeout) fontStyle |= FontStyle.Strikeout;
                if (_headFontUnderline) fontStyle |= FontStyle.Underline;

                pgHeader.StrFont = new Font(_headFontName, (float)Convert.ToDouble(_headFontSize.ToLower().Replace("px", "").Replace("pt", "")), fontStyle, GraphicsUnit.Point);
                pgHeader.StrColor = (Color)PrintTool.StrToColor(_headFontColor);
                if (_headLineDraw)                                // 绘制分割线
                {
                    pgHeader.LineDraw = _headLineDraw;
                    pgHeader.LineWidth = _headLineWidth;
                    pgHeader.LineColor = (Color)PrintTool.StrToColor(_headLineColor);
                    pgHeader.LineDash = PrintTool.GetDashStyle(_headLineDash);
                }

                // 页眉绘制
                pgHeader.Draw(g);
            }
        }

        /// <summary>
        /// 绘制页脚
        /// </summary>
        /// <param name="g">绘图对象</param>
        private void DrawFooter(Graphics g)
        {
            // 是否绘制
            if (_footDraw)
            {
                // 页脚实例
                PageFooter pgFooter = new PageFooter();

                // 页脚矩形
                RectangleF pgFooterRect = new RectangleF(TableRect.X,                     // X 坐标
                                                         TableRect.Y + TableRect.Height,  // Y 坐标      
                                                         TableRect.Width,                // W 宽度
                                                         mmToPixel(_footHeight)           // H 高度
                                                         );
                // 页脚赋值
                pgFooter.FootRect = pgFooterRect;
                pgFooter.StrLeft = ReplacePageNum(_footLeft);     // 左侧文本
                pgFooter.StrCenter = ReplacePageNum(_footCenter); // 中间文本 
                pgFooter.StrRight = ReplacePageNum(_footRight);   // 右侧文本
                FontStyle fontStyle = FontStyle.Regular;          // 字体样式
                if (_footFontBold) fontStyle |= FontStyle.Bold;
                if (_footFontItalic) fontStyle |= FontStyle.Italic;
                if (_footFontStrikeout) fontStyle |= FontStyle.Strikeout;
                if (_footFontUnderline) fontStyle |= FontStyle.Underline;

                pgFooter.StrFont = new Font(_footFontName, (float)Convert.ToDouble(_footFontSize.ToLower().Replace("px", "").Replace("pt", "")), fontStyle, GraphicsUnit.Point);
                pgFooter.StrColor = (Color)PrintTool.StrToColor(_footFontColor);
                if (_footLineDraw)                                // 绘制分割线
                {
                    pgFooter.LineDraw = _footLineDraw;
                    pgFooter.LineWidth = _footLineWidth;
                    pgFooter.LineColor = (Color)PrintTool.StrToColor(_footLineColor);
                    pgFooter.LineDash = PrintTool.GetDashStyle(_footLineDash);
                }

                // 页脚绘制
                pgFooter.Draw(g);
            }
        }

        #endregion

        #region 辅助方法

        /// <summary>
        /// 毫米 TO 像素
        /// </summary>
        /// <param name="mmValue">毫米值</param>
        /// <returns></returns>
        public static float mmToPixel(float mmValue) //mmValue是毫米,1厘米=10毫米
        {
            return (mmValue / 25.4f * 100f);
        }

        /// <summary>
        /// 替换 当前页码、总共页数两个变量
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private string ReplacePageNum(string str)
        {
            string retStr = "";
            if (str == null || str.Trim() == "")
                return retStr;
            retStr = str;
            int t = 0;
            while (t >= 0)
            {
                t = retStr.IndexOf("[curpage]", StringComparison.OrdinalIgnoreCase);
                if (t >= 0)
                {
                    retStr = retStr.Substring(0, t) + RptDraw.CurPageNum.ToString() + retStr.Substring(t + "[curpage]".Length);
                }
            }

            t = 0;
            while (t >= 0)
            {
                t = retStr.IndexOf("[allpage]", StringComparison.OrdinalIgnoreCase);
                if (t >= 0)
                {
                    retStr = retStr.Substring(0, t) + RptDraw.AllPageNum.ToString() + retStr.Substring(t + "[allpage]".Length);
                }
            }
            return retStr;
        }

        /// <summary>
        /// 解析XML文件
        /// </summary>
        /// <returns>返回成功与否</returns>
        private bool ParseXML()
        {
            if (this.DATAXML == null || this.DATAXML.Trim() == "") return false;
            XmlDataDocument xmlDoc = new XmlDataDocument();
            try
            {
                xmlDoc.LoadXml(this.DATAXML);
                XmlNode rootNode = xmlDoc.DocumentElement;
                if (rootNode.ChildNodes.Count == 0) return false;
                if (rootNode.ChildNodes[0].Name.ToLower() != "table") return false;

                XmlNode tableNode = rootNode.ChildNodes[0]; // 表格节点
                HtmlHeight = float.Parse(tableNode.Attributes["height"].Value);
                HtmlWidth = float.Parse(tableNode.Attributes["width"].Value);

                int tmRowIndex = 0;
                foreach (XmlNode trNode in tableNode.ChildNodes)
                {
                    if (trNode.Name.ToLower() != "tr") continue;

                    // 解析表格行
                    Row tmRow = new Row();
                    tmRow.RowIndex = tmRowIndex;
                    tmRow.RowHeight = float.Parse(trNode.Attributes["height"].Value);
                    tmRow.RowType = trNode.Attributes["rowtype"].Value.ToLower();

                    // 解析单元格
                    foreach (XmlNode tdNode in trNode.ChildNodes)
                    {
                        Cell tmCell = new Cell();

                        #region 合并\坐标\矩形

                        tmCell.RowSpan = Convert.ToInt32(tdNode.Attributes["rowspan"].Value);
                        tmCell.ColSpan = Convert.ToInt32(tdNode.Attributes["colspan"].Value);
                        tmCell.RowIndex = Convert.ToInt32(tdNode.Attributes["r"].Value);
                        tmCell.ColIndex = Convert.ToInt32(tdNode.Attributes["c"].Value);
                        tmCell.RectX = float.Parse(tdNode.Attributes["x"].Value);
                        tmCell.RectY = float.Parse(tdNode.Attributes["y"].Value);
                        tmCell.RectW = float.Parse(tdNode.Attributes["w"].Value);
                        tmCell.RectH = float.Parse(tdNode.Attributes["h"].Value);

                        #endregion

                        #region 设置单元格字体

                        FontStyle tmStyle = new FontStyle();
                        tmStyle = FontStyle.Regular;
                        if (tdNode.Attributes["italic"].Value.ToString() == "1") tmStyle |= FontStyle.Italic;
                        if (tdNode.Attributes["bold"].Value.ToString() == "1") tmStyle |= FontStyle.Bold;
                        if (tdNode.Attributes["strikeout"].Value.ToString() == "1") tmStyle |= FontStyle.Strikeout;
                        if (tdNode.Attributes["underline"].Value.ToString() == "1") tmStyle |= FontStyle.Underline;
                        tmCell.CellFont = new Font(tdNode.Attributes["fontname"].Value, float.Parse(tdNode.Attributes["fontsize"].Value.Replace("pt", "").Replace("px", "")), tmStyle, GraphicsUnit.Point);
                        tmCell.FontColor = (Color)PrintTool.StrToColor(tdNode.Attributes["fontcolor"].Value);
                        tmCell.BackColor = (Color)PrintTool.StrToColor(tdNode.Attributes["backcolor"].Value);

                        StringFormat tmFormat = new StringFormat();
                        switch (tdNode.Attributes["align"].Value.ToLower())     // 水平对齐方式
                        {
                            case "center":
                                tmFormat.Alignment = StringAlignment.Center;
                                break;
                            case "right":
                                tmFormat.Alignment = StringAlignment.Far;
                                break;
                            default:
                                tmFormat.Alignment = StringAlignment.Near;
                                break;
                        }
                        switch (tdNode.Attributes["valign"].Value.ToLower())   // 垂直对齐方式
                        {
                            case "middle":
                                tmFormat.LineAlignment = StringAlignment.Center;
                                break;
                            case "bottom":
                                tmFormat.LineAlignment = StringAlignment.Far;
                                break;
                            default:
                                tmFormat.LineAlignment = StringAlignment.Near;
                                break;
                        }
                        tmCell.strFormat = tmFormat;

                        #endregion

                        #region 内嵌图片-属性

                        tmCell.IsImage = tdNode.Attributes["isimage"].Value.ToString() == "1" ? true : false;
                        if (tmCell.IsImage)
                            tmCell.ImageUrl = tdNode.Attributes["imageurl"].Value;
                        #endregion

                        #region 单元格边框属性

                        // 左边框线
                        string tmVal = tdNode.Attributes["leftwidth"].Value;
                        if (tmVal.IndexOf("px") >= 0)
                        {
                            tmCell.LeftBorder = new BorderLine(
                                                                float.Parse(tmVal.Replace("px", "")),
                                                                (Color)PrintTool.StrToColor(tdNode.Attributes["leftcolor"].Value),
                                                                PrintTool.GetDashStyle(tdNode.Attributes["leftdash"].Value)
                                                               );
                        }

                        // 上边框线
                        tmVal = tdNode.Attributes["topwidth"].Value;
                        if (tmVal.IndexOf("px") >= 0)
                        {
                            tmCell.TopBorder = new BorderLine(
                                                                float.Parse(tmVal.Replace("px", "")),
                                                                (Color)PrintTool.StrToColor(tdNode.Attributes["topcolor"].Value),
                                                                 PrintTool.GetDashStyle(tdNode.Attributes["topdash"].Value)
                                                              );

                        }

                        // 右边框线
                        tmVal = tdNode.Attributes["rightwidth"].Value;
                        if (tmVal.IndexOf("px") >= 0)
                        {
                            tmCell.RightBorder = new BorderLine(
                                                                  float.Parse(tmVal.Replace("px", "")),
                                                                  (Color)PrintTool.StrToColor(tdNode.Attributes["rightcolor"].Value),
                                                                  PrintTool.GetDashStyle(tdNode.Attributes["rightdash"].Value)
                                                               );
                        }

                        // 下边框线
                        tmVal = tdNode.Attributes["bottomwidth"].Value;
                        if (tmVal.IndexOf("px") >= 0)
                        {
                            tmCell.BottomBorder = new BorderLine(
                                                                  float.Parse(tmVal.Replace("px", "")),
                                                                  (Color)PrintTool.StrToColor(tdNode.Attributes["bottomcolor"].Value),
                                                                  PrintTool.GetDashStyle(tdNode.Attributes["bottomdash"].Value)
                                                                );
                        }

                        #endregion

                        #region 单据格数据数值

                        tmCell.Value = tdNode.InnerText;

                        #endregion

                        // 加入对应的行内
                        tmRow.RowCells.Add(tmCell);
                    }

                    RptDraw.RowsList.Add(tmRow);

                    tmRowIndex++;
                }
            }
            catch
            {
                return false;
            }
            finally
            {
                xmlDoc = null;
            }

            return true;
        }

        /// <summary>
        /// 计算报表区域矩形
        /// 真实的绘制报表的区域
        /// </summary>
        private void CalcTableRect()
        {
            // 重新初始化实例
            TableRect = new RectangleF();

            // 左顶点 X坐标
            TableRect.X = mmToPixel(_marginLeft);

            // 左顶点 Y坐标
            TableRect.Y = mmToPixel(_marginTop);
            if (_headDraw) // 需要绘制页眉
                TableRect.Y += mmToPixel(_headHeight);

            // 报表矩形宽度高度
            if (this.LANDSCAPE)  // 版型方向 横向
            {
                // 颠倒 宽高
                TableRect.Width = mmToPixel((float)_paperHeight - _marginLeft - _marginRight);
                TableRect.Height = mmToPixel((float)_paperWidth - _marginTop - _marginBottom);
            }
            else // 版型方向 纵向
            {
                TableRect.Width = mmToPixel((float)_paperWidth - _marginLeft - _marginRight);
                TableRect.Height = mmToPixel((float)_paperHeight - _marginTop - _marginBottom);
            }

            // 报表矩形高度缩减
            if (_headDraw) // 需要绘制页眉
                TableRect.Height -= mmToPixel(_headHeight);
            if (_footDraw) // 需要绘制页脚
                TableRect.Height -= mmToPixel(_footHeight);
        }

        /// <summary>
        /// 计算缩放比例
        /// </summary>
        private void CalcReportZoom()
        {
            if (this.ZOOMTYPE.ToLower() == "row")
            {
                if (Convert.ToInt32(TableRect.Width) >= HtmlWidth)
                    this.Zoom = 1;
                else
                    this.Zoom = TableRect.Width / HtmlWidth;
            }
            else if (this.ZOOMTYPE.ToLower() == "col")
            {
                if (Convert.ToInt32(TableRect.Height) >= HtmlHeight)
                    this.Zoom = 1;
                else
                    this.Zoom = TableRect.Height / HtmlHeight;
            }
            else
            {
                this.Zoom = 1;
            }
        }

        /// <summary>
        /// 转换所有的尺寸
        /// 根据缩放比例
        /// </summary>
        private void CalcZoomAllSize()
        {
            if (this.Zoom != 1)
            {
                // 转换HTML 高度宽度
                HtmlWidth = HtmlWidth * Zoom;
                HtmlHeight = HtmlHeight * Zoom;

                // 转换所有行号
                foreach (Row zRow in this.RptDraw.RowsList)
                {
                    // 行高缩小
                    zRow.RowHeight = zRow.RowHeight * Zoom;

                    // 转换所有单元格 
                    foreach (Cell zCell in zRow.RowCells)
                    {
                        zCell.RectX = zCell.RectX * Zoom;
                        zCell.RectY = zCell.RectY * Zoom;
                        zCell.RectW = zCell.RectW * Zoom;
                        zCell.RectH = zCell.RectH * Zoom;

                        zCell.TopBorder.LineWidth = zCell.TopBorder.LineWidth * Zoom;
                        zCell.BottomBorder.LineWidth = zCell.BottomBorder.LineWidth * Zoom;
                        zCell.LeftBorder.LineWidth = zCell.LeftBorder.LineWidth * Zoom;
                        zCell.RightBorder.LineWidth = zCell.RightBorder.LineWidth * Zoom;

                        // 字体相应缩小
                        zCell.CellFont = new Font(zCell.CellFont.Name, zCell.CellFont.Size * Zoom, zCell.CellFont.Style, GraphicsUnit.Point);

                    }
                }
            }
        }

        #endregion

    }
}



加载中
1
zabcd117
zabcd117

引用来自“zabcd117”的评论

如果不是要求全部兼容各种低端浏览器,只用css的media query就能实现完美的打印效果了,比这种方式实用性强太多了。

引用来自“生如秋叶”的评论

页眉,页脚固定,中间列表部分翻页,求不用服务器生成PDF/Word文档的解决方案
<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>print</title>
    <style type="text/css">
    html,body,p{padding:0;margin:0;}
    @media print {
        p { 
            position: relative;
            display: block;
            top:30pt;
            page-break-after: always;
            z-index: 0;
        }


        p:before, p:after{
          display:block;
          width:100%;
          height:2em;
          line-height:2em;
          position:fixed;
          background:gray;
        }


        p:before{
          top:0;
          content: 'page header';
        }


        p:after{
          bottom:0;
          content: 'page footer';
        }
    }
    </style>
</head>
<body>
    <p>page1</p>
    <p>page2</p>
    <p>page3</p>
</body>
</html>

这是一个简答你的例子,你在chrome下跑跑看看。



0
雲竹無心
雲竹無心
何必如此麻烦自己做,有一款网页打印插件就挺好用的,叫Lodop
0
zabcd117
zabcd117
如果不是要求全部兼容各种低端浏览器,只用css的media query就能实现完美的打印效果了,比这种方式实用性强太多了。
0
生如秋叶
生如秋叶

引用来自“zabcd117”的评论

如果不是要求全部兼容各种低端浏览器,只用css的media query就能实现完美的打印效果了,比这种方式实用性强太多了。
页眉,页脚固定,中间列表部分翻页,求不用服务器生成PDF/Word文档的解决方案
0
生如秋叶
生如秋叶

引用来自“zabcd117”的评论

如果不是要求全部兼容各种低端浏览器,只用css的media query就能实现完美的打印效果了,比这种方式实用性强太多了。

引用来自“生如秋叶”的评论

页眉,页脚固定,中间列表部分翻页,求不用服务器生成PDF/Word文档的解决方案

引用来自“zabcd117”的评论

<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>print</title>
    <style type="text/css">
    html,body,p{padding:0;margin:0;}
    @media print {
        p { 
            position: relative;
            display: block;
            top:30pt;
            page-break-after: always;
            z-index: 0;
        }


        p:before, p:after{
          display:block;
          width:100%;
          height:2em;
          line-height:2em;
          position:fixed;
          background:gray;
        }


        p:before{
          top:0;
          content: 'page header';
        }


        p:after{
          bottom:0;
          content: 'page footer';
        }
    }
    </style>
</head>
<body>
    <p>page1</p>
    <p>page2</p>
    <p>page3</p>
</body>
</html>

这是一个简答你的例子,你在chrome下跑跑看看。



谢谢你的回答,可能我之前写的太简单了。这种套打场景,首先,页眉页脚并不是简单的几行文字,往往很复杂;其次,中间的列表项并不是固定的,只有在列表项超出一页的范围时才需要换页(还得有页码 ,如1/3这样);再次,纸张大小也是不确定的,用A4竖着打还是用B5横着打取决于用户的心情。
zabcd117
zabcd117
页眉页脚如果想定制的话,也不难,纸张问题真的就是一点没有,你可以在chrome下试试,完全取决你的样式排版,只不过可能兼容性稍差。还有就是,如果做非常复杂的打印,可能就不单单只用:before和:after这么简单了,需要把页眉和页脚变成实体元素,在screen下都隐藏,在print下才显示出来。
0
酷酷的就
酷酷的就
看看锐浪的
返回顶部
顶部