【转】C# PrintDocument打印 多页 打印预览

PrintDocument实例所有的订阅事件如下:


1.创建一个PrintDocument的实例.如下:
System.Drawing.Printing.PrintDocument docToPrint = 
   new System.Drawing.Printing.PrintDocument(); 
2.设置打印机开始打印的事件处理函数.函数原形如下:
void docToPrint_PrintPage(object sender, 
   System.Drawing.Printing.PrintPageEventArgs e) 
3.将事件处理函数添加到PrintDocument的PrintPage事件中。
docToPrint.PrintPage+=new PrintPageEventHandler(docToPrint_PrintPage); 
4.设置PrintDocument的相关属性,如:
PrintDialog1.AllowSomePages = true;PrintDialog1.ShowHelp = true; 
5.把PrintDialog的Document属性设为上面配置好的PrintDocument的实例:
PrintDialog1.Document = docToPrint; 
6.调用PrintDialog的ShowDialog函数显示打印对话框:
DialogResult result = PrintDialog1.ShowDialog(); 
7.根据用户的选择,开始打印:
if (result==DialogResult.OK)
   {
    docToPrint.Print();
   } 
8.打印预览控件PrintPreviewDialog
例子如下:


使用时先创建PrintService类的实例,然后调用void StartPrint(Stream streamToPrint,string streamType)函数开始打印。其中streamToPrint是要打印的内容(字节流),streamType是流的类型(txt表示普通文本,image表示图像);


public partial class PrintTxt  

      private   PrintPreviewDialog PrintPreview = new PrintPreviewDialog(); 
      private   string    StreamType; 
      private   Image image = null; 
      private   Stream StreamToPrint = null; 
      Font mainFont = new Font("宋体", 12);//打印的字体 
      public string Filename =null; 
        
        
    //1、实例化打印文档 
    PrintDocument pdDocument = new PrintDocument(); 
    private string[] lines; 
    private int linesPrinted; 
 
 
    public PrintTxt(string filepath,string filetype) 
    { 
          
 
         Filename = Path.GetFileNameWithoutExtension(filepath); 
 
        //订阅BeginPrint事件 
        pdDocument.BeginPrint += new PrintEventHandler(pdDocument_BeginPrint); 
        //訂閱EndPrint事件,释放资源 
       
          
        pdDocument.PrintPage += new PrintPageEventHandler(OnPrintPage); 
 
 
        //订阅Print打印事件,该方法必须放在订阅打印事件的最后 
        FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read); 
        StartPrint(fs, filetype); 
 
 
        //打印结束 
        pdDocument.EndPrint += new PrintEventHandler(pdDocument_EndPrint); 
 
 
 
    } 
 
    //2、启动Print打印方法 
    public   void StartPrint(Stream streamToPrint, string streamType) 
    { 
 
        //返回值的PageSettings A4\A5 
        PageSettings ps = new PageSettings(); 
         //显示设置打印页对话框 
     PageSetupDialog Psdl = new PageSetupDialog(); 
 
        //打印多份设置,注意,该方法需放在printpage方法后面。 
     PrintDialog pt = new PrintDialog(); 
        pt.AllowCurrentPage = true; 
        pt.AllowSomePages = true; 
        pt.AllowPrintToFile = true; 
 
         StreamToPrint = streamToPrint;//打印的字节流 
     StreamType = streamType; //打印的类型 
     pdDocument.DocumentName = Filename; //打印的文件名 
 
     Psdl.Document = pdDocument; 
        PrintPreview.Document = pdDocument; 
        pt.Document = pdDocument; 
 
        Psdl.PageSettings = pdDocument.DefaultPageSettings; 
        try
        { 
            //显示对话框 
 
            if (Psdl.ShowDialog() == DialogResult.OK) 
            { 
                ps = Psdl.PageSettings; 
                pdDocument.DefaultPageSettings = Psdl.PageSettings; 
            } 
 
            if (pt.ShowDialog() == DialogResult.OK) 
            { 
                pdDocument.PrinterSettings.Copies = pt.PrinterSettings.Copies; 
                pdDocument.Print(); 
            } 
           if(PrintPreview.ShowDialog()==DialogResult.OK ) 
            //调用打印 
              pdDocument.Print(); 
 
              
             * PrintDocument对象的Print()方法在PrintController类中执行PrintPage事件。 
             */ 
        } 
        catch (InvalidPrinterException ex) 
        { 
            MessageBox.Show(ex.Message, "Simple Editor", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            throw; 
        } 
    } 
 
    /// <summary> 
    /// 3、得到打印內容 
    /// 每个打印任务只调用OnBeginPrint()一次。 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    void pdDocument_BeginPrint(object sender, PrintEventArgs e) 
    { 
        char[] param = { '\n' }; 
        char[] trimParam = { '\r' };//回车 
 
        switch (StreamType) 
        { 
            case "txt": 
                StringBuilder text = new StringBuilder(); 
                System.IO.StreamReader streamReader = new StreamReader(StreamToPrint, Encoding.Default); 
                while (streamReader.Peek() >= 0) 
                { 
                    lines = streamReader.ReadToEnd().Split(param); 
                    for (int i = 0; i < lines.Length; i++) 
                    { 
                        lines[i] = lines[i].TrimEnd(trimParam); 
                    } 
                } 
 
                break; 
            case "image": 
                image = System.Drawing.Image.FromStream(StreamToPrint); 
                break; 
            default: 
                break; 
        } 
 
    } 
 
 
 
    /// <summary> 
    /// 4、绘制多个打印界面 
    /// printDocument的PrintPage事件 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void OnPrintPage(object sender, PrintPageEventArgs e) 
    { 
        int leftMargin = Convert.ToInt32((e.MarginBounds.Left) * 3 / 4);  //左边距 
        int topMargin = Convert.ToInt32(e.MarginBounds.Top * 2 / 3);    //顶边距 
        switch (StreamType) 
        { 
            case "txt": 
                while (linesPrinted < lines.Length) 
                { 
                    //向画布中填写内容 
                    e.Graphics.DrawString(lines[linesPrinted++], new Font("Arial", 10), Brushes.Black, leftMargin, topMargin, new StringFormat()); 
 
                    topMargin += 55;//行高为55,可调整 
 
                    //走纸换页 
                    if (topMargin >= e.PageBounds.Height - 60)//页面累加的高度大于页面高度。根据自己需要,可以适当调整 
                    { 
                        //如果大于设定的高 
                        e.HasMorePages = true; 
 
                         /* 
                         * PrintPageEventArgs类的HaeMorePages属性为True时,通知控件器,必须再次調用OnPrintPage()方法,打印一个页面。 
                         * PrintLoopI()有一个用於每个要打印的页面的序例。如果HasMorePages是False,PrintLoop()就会停止。 
                         */
                        return; 
                    } 
                } 
 
                break; 
            case "image"://一下涉及剪切图片, 
                int width = image.Width; 
                int height = image.Height; 
                if ((width / e.MarginBounds.Width) > (height / e.MarginBounds.Height)) 
                { 
                    width = e.MarginBounds.Width; 
                    height = image.Height * e.MarginBounds.Width / image.Width; 
                } 
                else
                { 
                    height = e.MarginBounds.Height; 
                    width = image.Width * e.MarginBounds.Height / image.Height; 
                } 
                  
                System.Drawing.Rectangle destRect = new System.Drawing.Rectangle(topMargin, leftMargin, width, height); 
                //向画布写入图片 
                for (int i = 0; i < Convert.ToInt32(Math.Floor((double)image.Height/ 820)) + 1; i++) 
                { 
                     
                    e.Graphics.DrawImage(image, destRect, i*820,i*1170 , image.Width, image.Height, System.Drawing.GraphicsUnit.Pixel); 
                    //走纸换页 
                    if (i * 1170 >= e.PageBounds.Height - 60)//页面累加的高度大于页面高度。根据自己需要,可以适当调整 
                    { 
                        //如果大于设定的高 
                        e.HasMorePages = true; 
 
                        /* 
                        * PrintPageEventArgs类的HaeMorePages属性为True时,通知控件器,必须再次調用OnPrintPage()方法,打印一个页面。 
                        * PrintLoopI()有一个用於每个要打印的页面的序例。如果HasMorePages是False,PrintLoop()就会停止。 
                        */
                        return; 
                    } 
                } 
              
                break; 
        } 
 
        //打印完毕后,画线条,且注明打印日期 
        e.Graphics.DrawLine(new Pen(Color.Black), leftMargin, topMargin, e.MarginBounds.Right, topMargin);  
 
        string strdatetime = DateTime.Now.ToLongDateString() + DateTime.Now.ToLongTimeString(); 
        e.Graphics.DrawString(string.Format("打印时间:{0}", strdatetime), mainFont, Brushes.Black, e.MarginBounds.Right-240, topMargin+40, new StringFormat()); 
        linesPrinted = 0; 
        //绘制完成后,关闭多页打印功能 
        e.HasMorePages = false; 
 
    } 
 
 
    /// <summary>   
    ///5、EndPrint事件,释放资源 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    void pdDocument_EndPrint(object sender, PrintEventArgs e) 
    { 
 
        //变量Lines占用和引用的字符串数组,现在释放 
        lines = null; 
    } 
     

//PrintTxt simple = new PrintTxt("D:\\Mainsoft\\12.txt", "txt");

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如何快速创建水晶报表 <br>如何编写带图片的报表 <br>如何使图片成为整个报表的背景 <br>如何设置水晶报表中节的背景图片<br>如何设置水晶报表中节的背景色 <br>如何设置水晶报表的页面 <br>如何在报表中添加节 <br>如何在报表中移动节的顺序 <br>如何在报表中合并节 <br>如何在报表中册除节 <br>如何在报表中显示与隐藏节 <br>如何设置多列样式报表 <br>如何设置报表中节的高度 <br>如何设置报表的摘要信息 <br>如何设置报表的打印日期与时间 <br>报表格式化类对象技巧 <br>如何在报表中使用文本对象 <br>如何移动对象操作 <br>如何对齐多个对象 <br>如何使用公式字段 <br>如何在报表中使用线 <br>如何在报表中使用方框 <br>报表数据排序与分组技巧<br>如何排序报表数据 <br>如何报表数据分组 <br>如何报表中筛选数据 <br>如何对分组报表中的页码进行设置 <br>报表的应用技巧 <br>如何在水晶报表中使用交叉表 <br>如何在水晶报表中使用子报表 <br>如何动态显示子报表 <br>如何删除子报表 <br>如何在报表中计算百分比 <br>Windows打印控件应用技巧 <br>如何使用PrintDocument控件打印窗体数据 <br>如何使用PrintPreviewContronl控件预览 <br>使用PrintPreviewDialog对话框 <br>如何使用PrintDialog对话框打印 <br>如何使用PageSetupDialog对话框设置页面 <br>如何使用PrintDocument控件打印文本文件 
姓 名: 周方勇 网 名: 长江支流/咏方舟 Email: [email protected] Blog: http://blog.csdn.net/flygoldfish 2004年04月18日 1、在网友的热心支持下免费提供空间和域名 www.webmis.com.cn 2004年04月07日 发布不带.dll的源码供交流 2005年01月24日 1、提供VB.NET及C#使用示例工程 2、发布V2.2测试版 2005年01月22日 将打印示例程序按功能(简单打印、完整示例、Excel打印)分在不同的窗口 2005年01月14日 发布《MIS金质打印通》 V2.1测试版 2004年01月13日 1、将MisPrinter类改为MisGoldPrinter,以促进品牌效应。 2、在MisGoldPrinter类中再增加一个带参构造函数,以便直接默认横向打印/预览 3、增加DocumentName属性,以便在打印/预览时在窗口标题栏中显示指定的名称 2004年01月07日 调整打印程序内部结构,为使发出去的后期源程序版本一致,待近期调整完结构之后公布源码! 这就是继V1.1之后没有发源代码的原因。 ____________________________________________________ 2004年7月 完成了整体的框架、涉及打印的几个对话框、核心打印程序及几个基本打印对象并由BillPrinter类将其组织起来,程序基本定型。 本程序为通用打印程序,单据、会计凭证、发票清单、报表、任意复杂表格、合并表格如工矿企业合同都可以由系统提供的几个默 认打印对象组合打印DataGrid、DataTable、MSHFlexGrid等二维形式全部可以打印。 部分对象如PrinterMargins、Sewing、GridLineFlag、GridMergeFlag等提供图例,以促进理解。 后期版本将提供XML描述、SQL数据源的打印,并用管理器管理任意多个网格、文本对象、图象等,用户可以随意定义。 2004年8月初 为一些类或程序写上注释,如下: /// 程序提供:周方勇;Email:[email protected]。 /// 请 关 注:WebMIS.Net快速开发工具,不写一行程序开发B/S架构下MIS、OA、CRM、人事管理、档案管理等数据库网页系统。简单、实用、稳定、可靠。 /// 下 载: /// 上海奥联:WWW.AlinkSoft.COM /// 用友华表:WWW.CellSoft.CC ///★★★★★您可以免费使用此程序,但是请您保留此说明,以维护知识产权★★★★★ 2004年08月07日 1、将框架作了部分调整,并且将打印基本对象的基类Printer作了调整。 由于打印对象的定位及打印区域受PrintDocument、Sewing影响,为了方便Printer的子类不必在每次实例化后设置这 两个对象,故将PrintDocument、Sewing放在一个类中作为全局静态变量,现删除这两个全局静态变量, 改在Printer 的构造函数中,为每个子类提供一个默认的PrintDocument、Sewing实例对象。 2、为GridBase扩充了几个属性与方法,由于字段太多,每次增加或修改字段后要去构造函数中去修改他们的初始化, 太麻烦了,所以将它们的初始化直接放在定义处,并把相应的属性及相关方法直接放在字段后,并用#region指令将 它们折叠起来,便于维护。 3、增加了ReDimArrString(string[,] arrStr,int rows,int cols),即重定义二维字符数组,因为网格的行列数可能要改 变,但不能因为它们改变了而丢失原有的数据,因此写此程序保留新定义的行列,但保留和原有行列数相交的部分数据。 4、应用设计模式原理重新组织IPrinterPageSetting、PrinterPageSetting、WinPrinterPageSetting、WebPrinterPageSetting。 WebPrinterPageSetting待进一步完善。 2004年08月08日 1、将以往程序优化 2、将DrawGrid类中DrawGridLine(...)、DrawGridText(...)、DrawGridBorder(...)参数最全的核心函数改为protected,提供public的 无参方法供实例化对象调用; 由于在指定的区域内可能绘制不完网格,因此上面的几个函数可能会将返回类型void改为一个描述绘制结果的对象; SetText(int row,int col,string text)、SetText(int row,int col)将在后期版本中提供.Row[index].Text的属性; TransGrid()、ResetTransGrid()是在设计时为了能做任意的缩放的变换提供的,待进一步完善。 3、对Printer类中的ReSetVariableVal()、GetPrinterMargins()进行修改,以适应对纸张进行调整特别是横向、竖向打印的支持。 2004年08月09日 1、解决分页问题,主要是有些对象每页都重复打印,使得条件复杂。 2004年08月10日 1、13:42将源程序传给资深程序员李峰; 2、计划增加每页小计。 2004年08月11日 1、为网格增加画对角线的功能,以满足中国人表格的特点; 2、将Graphics、PrintDocument、Sewing、RectangleF、Height、Draw()重新组织在IDraw里,并在 BillPrinter中增加private void OutObject(IDraw outer),使每个对象输出时调用此方法,提高代码重用率; 2004年08月14日 1、忘了,反正又把程序看了看,修修补补做了些调整。 2004年08月15日 1、将分页又重新简化了一下,主要是打印Body上用了数据行指针; 2004年08月16日 1、发布V1.0源码版,程序名称为MIS金质打印王。 2、在CSDN上发布贴子: .^^.开源:C#.NET开发的MIS打印程序,各种网格如DataGrid打印DataTable、HtmlTable等二维形式全搞定,源码免费下载 http://community.csdn.net/Expert/topic/3278/3278050.xml?temp=.5012934 2004年08月17日 1、在CSDN上发布文章: 开源:.NET环境下有关打印页面设置、打印机设置、打印预览对话框的实现 http://blog.csdn.net/flygoldfish/archive/2004/08/17/77208.aspx 2、应广大网友来信要求,计划将PrinterPageSetting目录开源到演示程序,以后逐一以文章的形式全部开放。 2004年08月18日 1、中国共享软件网收录 MIS金质打印王 V1.0源码版 http://www.shareware.cn/pub/2319.html 2、将PrinterPageSetting目录即(页面设置、打印机设置、打印预览)源码加入演示程序。 3、在MisGoldPrinter中添加属性,DataSource,这样,仅需几句话就可以打印了,如: MisGoldPrinter webmis = new MisGoldPrinter(); //申明并实例化打印组件 webmis.Title = "WebMIS.Net快速开发工具\nWWW.AlinkSoft.COM"; //网格标题 webmis.DataSource = this.dataGrid1; //DataGrid作为数据源 webmis.Preview(); //打印预览 注意:将将MisGoldPrinter中的Draw(Graphics g)打印各个对象时加一下 printerobject != null的判断,如 if (mCurrentPageIndex == 1 || _caption.IsDrawAllPage)... 改为 if (_caption != null && (mCurrentPageIndex == 1 || _caption.IsDrawAllPage))... 否则可能会出错。 4、将3的应用加到了frmPrint.cs ,做一个简单的打印。 2004年08月19日 1、将PrinterPageSetting目录即(页面设置、打印机设置、打印预览)源码加入演示程序。 2、发布V1.1源码版,程序名称为MIS金质打印王。 2004年09月03日 1、由于在CSDN上发表文档".NET环境下有关打印页面设置、打印机设置、打印预览对话框的实现", 因此将PrinterPageSetting封装成一个.dll,分别用C#与VB.net写了使用示例工程程序 2、在IPrinterPageSetting.cs增加event PrintPageDelegate PrintPage,并将原PrintPage改为PrintPageValue /// C#调用: /// PrinterPageSetting1.PrintPageValue = new PrintPageDelegate(this.PrintPageEventHandler); ///或 PrinterPageSetting1.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler); /// VB调用: /// Me.printerPageSetting.PrintPageValue = New GoldPrinter.PrintPageDelegate(AddressOf printDocument_PrintPage) 3、增加了DrawText类,用以打印文档(其实可以用一行一列的DrawGrid打印) 4、PrinterPageSetting的readme.txt如下: ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 声明: 1、版权归周方勇所有,如需传播,请保留完整的内容及此声明,以维护知识产权! 2、您可以使用本程序中的任何部分作为学习或商业用途,但是需要保留相关程序的注释。 3、最新版本下载:http://www.alinksoft.com 4、免费源码 5、本人不承担任何责任。 周方勇;Email:[email protected]。 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 本程序带C#与VB.net版本使用方式,用VS.net打开PrinterPageSetting.sln, 在您喜欢的语言项目上单击鼠标右键,在弹出的菜单中选择"设为启动项目",然后运行。 5、准备独立发布PrinterPageSetting 2004年09月04日 重大喜讯:收到中国共享软件注册中心2004年09月03日的邮件。部分内容如下: 软件名称:MISGoldPrinter免费C#.NET源码版(5块钱给softreg吧) 注册价格:5元/套 您的软件在本站的编号是: /535AC7A1-9985-4314-A52C-978BB9C0BB29/ 软件注册页绝对链接: http://www.softreg.com.cn/shareware_view.asp?id=/535AC7A1-9985-4314-A52C-978BB9C0BB29/ 快捷链接: http://www.softreg.com.cn/shareware.asp?id=17260 2004年10月...日 改变PrintDocument的DefaultPageSettings就会改变PrinterMargins。由于是打印基类,继承者博多,因此 每次实例化时都会计算PrinterMargins会影响效率,这就是前些版本速度慢的原因。改为手动调用CalculatePageInfo()或改变 PrintDocument后在调用处重新计算一个PrinterMargins保存起来,因此增加PrinterSingleton, 使系统只有同一个PrintDocument及PrinterMargins,这样速度大大改观。 开发Excel打印功能 2004年11月20日 开发Excel打印功能完成,能够生成Excel文件、Excel打印预览、Excel操作。 自定制模板打印,非常灵活。完成各种打印、套打、报表、图表分析。 2004年11月23日 发布MIS金质打印王 V2.0测试版。如需要源码,下载V1.1即可。 V2.0源码版在预计在12月上旬推出。 2004年11月27日 改正预览时显示正确,在预览窗口单击打印打印不出Body的错误。 其实只要在PrintPageEventHandler()中打印预览重置当前页及当前行 this.mCurrentPageIndex = 1; this.mCurrentRowIndex = 0; 2004年12月...日 1、调整打印程序内部结构,公开部分程序基本没动,只作相应的错误更正及加几个属性。 2、PrinterBase不再包含装订线Sewing,打印对象的定位及打印区域只受PrintDocument的影响, 3、由于使用PrinterSingleton使系统只有同一个PrintDocument及PrinterMargins,因此在同一系统 两个地方使用时出现了打印一样的效果,如A处有header而B处没有,先打A再打B,结果B中也有header了, 于是在PrinterSingleton增加Reset()方法以使PrintDocument及PrinterMargins为null,在MisPrinter 构造函数中首先调用Reset()

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值