C# winform通用打印方法

首先画好UserControl

然后有两种打印方式:

1,PrintControl

2,PrintControlByDraw

具体见下面的代码(部分根据您的实际情况做适当修改):

     PrintControl方式:
     ///
<summary> /// 打印控件,在调用该控件前, /// 优点:性能好 /// 缺点:斑马打印机打出的内容很不清晰 /// </summary> /// <param name="docName">打印文档名称,即打印任务队列中的名称</param> /// <param name="printerName">使用哪个打印机来打印,即设备和打印机中的打印机名称</param> /// <param name="ucToPrint">要打印的控件对象</param> /// <param name="isPrintView">是否只进行预览,不真正打印</param> public static void PrintControl(string docName, string printerName, UserControl ucToPrint,bool isPrintView) { using (var printDoc=new PrintDocument()) { if (!string.IsNullOrEmpty(printerName)) { printDoc.DefaultPageSettings.PrinterSettings.PrinterName = printerName; } printDoc.DocumentName = docName; printDoc.PrintPage += (sender, e) => { ucToPrint.Show(); var bitMap = new Bitmap(ucToPrint.Width, ucToPrint.Height); ucToPrint.DrawToBitmap(bitMap, new Rectangle(0, 0, ucToPrint.Width, ucToPrint.Height)); //e.Graphics.DrawImageUnscaled(bitMap, Point.Empty); e.Graphics.DrawImage(bitMap, Point.Empty); }; printDoc.PrintController = new StandardPrintController(); if (isPrintView) { using (var printViewDlg = new PrintPreviewDialog()) { printViewDlg.Document = printDoc; (printViewDlg as Form).WindowState = FormWindowState.Maximized; printViewDlg.ShowDialog(); }//using } else { printDoc.Print(); } }//using }//fun


PrintControlByDraw 方式:
     ///
<summary> /// 通过重新绘制来打印控件 /// 优点:无论何种打印机都可以清晰打印 /// 缺点:性能稍差 /// </summary> /// <param name="docName">打印文档名称,即打印任务队列中的名称</param> /// <param name="printerName">使用哪个打印机来打印,即设备和打印机中的打印机名称</param> /// <param name="ucToPrint">要打印的控件对象</param> /// <param name="isPrintView">是否只进行预览,不真正打印</param> public static void PrintControlByDraw(string docName, string printerName, UserControl ucToPrint, bool isPrintView) { using (var printDoc = new PrintDocument()) { if (!string.IsNullOrEmpty(printerName)) { printDoc.DefaultPageSettings.PrinterSettings.PrinterName = printerName; } printDoc.DocumentName = docName; printDoc.PrintPage += (sender, e) => { //调用的目的是为了执行Load方法,加载控件信息 //当然,如果你在控件的构造方法中已加载信息,那么 //这个方法可以不调用 ucToPrint.Show(); DrawControlContent(ucToPrint, e.Graphics, Brushes.Black); }; printDoc.PrintController = new StandardPrintController(); if (isPrintView) { using (var printViewDlg = new PrintPreviewDialog()) { printViewDlg.Document = printDoc; (printViewDlg as Form).WindowState = FormWindowState.Maximized; printViewDlg.ShowDialog(); }//using } else { printDoc.Print(); } }//using }//fun /// <summary> /// 绘制控件上的DataGridView /// </summary> /// <param name="dgv"></param> /// <param name="g"></param> /// <param name="b"></param> /// <param name="pt">DataGridView的坐标</param> /// <param name="columnHeaderTopMargin">列这一行的上边距</param> private static void DrawDataGrid(DataGridView dgv, Graphics g, Brush b,Point pt,int columnHeaderTopMargin) { //var bitMap = new Bitmap(dgv.Width, dgv.Height); //dgv.DrawToBitmap(bitMap, new Rectangle(pt.X,pt.Y, dgv.Width, dgv.Height)); //g.DrawImage(bitMap, Point.Empty); Point dgvPt = pt; dgvPt.Y += columnHeaderTopMargin;//列头上边距 using (Font colFont = new Font(dgv.Font, FontStyle.Bold))//列字体要加粗 { foreach (DataGridViewColumn col in dgv.Columns) { g.DrawString(col.HeaderText, colFont, b, dgvPt); dgvPt.X += col.Width; } } dgvPt.X = pt.X; dgvPt.Y += dgv.ColumnHeadersHeight; //需要再减一点,不然第一行离列头有点远 int yToCut = 3;//单位为像素 if (dgvPt.Y>yToCut) { dgvPt.Y -= yToCut; } foreach (DataGridViewRow r in dgv.Rows) { foreach (DataGridViewCell cell in r.Cells) { int textWidth = (int)(g.MeasureString(cell.Value.ToString(), dgv.Font).Width); int textRowCount = textWidth / cell.OwningColumn.Width; if (textRowCount < 1) { textRowCount = 1; } g.DrawString(cell.Value.ToString(), dgv.Font, b, new Rectangle(dgvPt.X, dgvPt.Y, cell.OwningColumn.Width, r.Height * textRowCount)); dgvPt.X += cell.OwningColumn.Width; } dgvPt.X = pt.X; dgvPt.Y += r.Height; } } /// <summary> /// 绘制控件内容 /// </summary> /// <param name="c">要绘制的控件</param> /// <param name="g">打印机的绘图画面,使用它来将内容绘制到打印机上</param> /// <param name="b">使用的画刷</param> private static void DrawControlContent(Control c, Graphics g,Brush b) { foreach (Control subC in c.Controls) { if (subC.HasChildren) { DrawControlContent(subC, g,b); Point pt = new Point(0, 0); GetControlAbsoluteLocation(subC, ref pt); if (subC is Panel) { //Panel直接需要划横线 g.DrawLine(Pens.Black, new Point(pt.X,pt.Y+subC.Height), new Point(pt.X+subC.Width,pt.Y+subC.Height)); } else if (subC is DataGridView) { DrawDataGrid(subC as DataGridView, g, b, pt,3); } } else { Point pt = new Point(0, 0); GetControlAbsoluteLocation(subC, ref pt); if (subC is Label) { g.DrawString(subC.Text, subC.Font, b, pt); } else if (subC is PictureBox) { g.DrawImage((subC as PictureBox).Image,new Rectangle(pt.X,pt.Y,subC.Width,subC.Height) ); } } }//foreach } /// <summary> /// 获取控件的绝对位置, /// 即控件相对于Form的坐标 /// </summary> /// <param name="c"></param> /// <param name="pt">返回的坐标信息</param> private static void GetControlAbsoluteLocation(Control c,ref Point pt) { if (c.Parent == null) { return; } if (c is Form) { return; } pt.X += c.Location.X; pt.Y += c.Location.Y; GetControlAbsoluteLocation(c.Parent, ref pt); }
       
      示例:
       //
ucTest就是一个UserControl        using (ucTest uc = new ucTest(orderDto)) { OrderPrint.PrintControlByDraw("发货单",printerName, uc, isPrintPreview); // OrderPrint.PrintControl("发货单",printerName, uc, isPrintPreview); }
原文地址:https://www.cnblogs.com/imap/p/2873118.html