这几天做的功能用到了打印这个功能,直接在网上找了点demo,在这里做个备份。
1、直接打印DataTable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Printing;
using System.Data; namespace CheckCargoNumber.Common
{ public class PrintInfo
{
public PrintInfo()
{
this.dataHead = "打印标题";
this.headFont = new Font("黑体", , FontStyle.Bold);
this.dataTip = "打印日期:" + DateTime.Now.ToShortDateString();
this.tipFont = new Font("宋体", );
this.dataFont = new Font("宋体", );
this.landscape = false;
this.autoWidth = true;
}
///
/// 获取设置标题头
///
public String dataHead { set; get; }
///
/// 获取或设置标题格式
///
public Font headFont { set; get; }
///
/// 获取或设置附加信息(打印时间等)
///
public String dataTip { set; get; }
///
/// 获取或设置附加信息字体格式(打印时间等)
///
public Font tipFont { set; get; }
///
/// 获取或设置数据字体格式
///
public Font dataFont { set; get; }
///
/// 获取或设置每列的宽度,当无设置或设置列数不正确时,列宽平均分配
///
public int[] widths { set; get; }
///
/// 设定是否是横向打印
///
public Boolean landscape { set; get; }
///
/// 是否根据比例自动调整至可打印宽度。默认自动调整。
///
public Boolean autoWidth { set; get; }
} public class HCPrintcs
{
int countNum = ;//整体打印的条数
DataTable printDt;
PrintInfo pInfo;
public void printDataTable(DataTable dt, PrintInfo p)
{
this.printDt = dt;
this.pInfo = p;
PrintDocument pd = new System.Drawing.Printing.PrintDocument();
PrinterSettings pss = new System.Drawing.Printing.PrinterSettings();
pss.DefaultPageSettings.Landscape = pInfo.landscape;
pd.PrinterSettings = pss; pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage); PrintPreviewDialog ppd = new PrintPreviewDialog();
ppd.Document = pd;
if (printDt == null)
{
MessageBox.Show("出错", "没有可以打印的数据", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (ppd.ShowDialog() == DialogResult.OK)
{
try
{
pd.Print();
}
catch (Exception ex)
{
MessageBox.Show("出错", ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void pd_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics graphic = e.Graphics;//获取绘图对象
int linesPerPage = ;//页面行号
int yPosition = ;//绘制字符串的纵向位置
int xPosition = ;//绘制字符串的横向位置
int leftMargin = e.MarginBounds.Left;//左边距
int topMargin = e.MarginBounds.Top;//上边距
string line = string.Empty;//读取的行字符串
int currentPageLine = ;//当前页读取的行数
SolidBrush brush = new SolidBrush(Color.Black);//刷子
//首先打印标题
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
Rectangle rect = new Rectangle(leftMargin, topMargin, e.MarginBounds.Width, e.MarginBounds.Height);
graphic.DrawString(pInfo.dataHead, pInfo.headFont, brush, rect, sf);
topMargin += ; //首先打印说明
sf = new StringFormat();
sf.Alignment = StringAlignment.Far;
Rectangle rect2 = new Rectangle(leftMargin, topMargin, e.MarginBounds.Width, e.MarginBounds.Height);
graphic.DrawString(pInfo.dataTip, pInfo.tipFont, brush, rect2, sf);
topMargin += ; linesPerPage = (int)((e.MarginBounds.Height - ) / (pInfo.dataFont.GetHeight(graphic) + ));//每页可打印的行数 //判断宽度是否有效,无效的话,重新平均定义
if (pInfo.widths == null || pInfo.widths.Length != printDt.Columns.Count)
{
int[] newit = new int[printDt.Columns.Count];
for (int i = ; i < printDt.Columns.Count; i++)
{
newit[i] = e.MarginBounds.Width / printDt.Columns.Count;
}
pInfo.widths = newit;
}
//判断是否要自动增加宽度
if (pInfo.autoWidth)
{
int[] newit = new int[printDt.Columns.Count];
int s = pInfo.widths.Sum();
for (int i = ; i < printDt.Columns.Count; i++)
{
newit[i] = pInfo.widths[i] * e.MarginBounds.Width / s;
}
pInfo.widths = newit;
}
//下面开始画表格
Point ptS;
Point ptE;
int ti = leftMargin;//先画竖道
//先判断要打印的数据(包括字段名称)是否多于每页可打印的行数,如果多则按每页可打印的行数算,否则按数据量算
float ft = (printDt.Rows.Count - countNum + > linesPerPage ? linesPerPage : (printDt.Rows.Count - countNum + )) * (pInfo.dataFont.GetHeight(graphic) + );//内容占的高度
for (int j = ; j <= printDt.Columns.Count; j++)
{
if (j > )
{//如果是第一条竖线,开始点不变
ti += pInfo.widths[j - ];
}
ptS = new Point(ti, topMargin);
ptE = new Point(ti, topMargin + ((int)Math.Round(ft, )));
graphic.DrawLine(Pens.Black, ptS, ptE);
}
//然后画上面封顶的横道。
ptS = new Point(leftMargin, topMargin);
ptE = new Point(ti, topMargin);
graphic.DrawLine(Pens.Black, ptS, ptE);
//然后,填入绘字段名称行
xPosition = leftMargin;
yPosition = topMargin;
for (int j = ; j < printDt.Columns.Count; j++)
{
line = printDt.Columns[j].ColumnName;
graphic.DrawString(line, pInfo.dataFont, brush, xPosition, yPosition + , new StringFormat());
xPosition += pInfo.widths[j];
}
topMargin = topMargin + ((int)Math.Round(pInfo.dataFont.GetHeight(graphic) + , ));
ptS = new Point(leftMargin, topMargin);
ptE = new Point(xPosition, topMargin);
graphic.DrawLine(Pens.Black, ptS, ptE);
linesPerPage--;//因为已经画了标题栏,所以每页可画的条数少1
//countNum记录全局行数,currentPageLine记录当前打印页行数。
while (countNum < printDt.Rows.Count)
{
if (currentPageLine < linesPerPage)
{
xPosition = leftMargin;
ft = currentPageLine * (pInfo.dataFont.GetHeight(graphic) + );//前面行数占的高度
yPosition = topMargin + ((int)Math.Round(ft, ));
//绘制当前行
for (int j = ; j < printDt.Columns.Count; j++)
{
line = printDt.Rows[countNum][j].ToString();
graphic.DrawString(line, pInfo.dataFont, brush, xPosition, yPosition + , new StringFormat());
xPosition += pInfo.widths[j];
} countNum++;
currentPageLine++;
//然后画下面的横道
ft = currentPageLine * (pInfo.dataFont.GetHeight(graphic) + );//前面行数占的高度
yPosition = topMargin + ((int)Math.Round(ft, ));
ptS = new Point(leftMargin, yPosition);
ptE = new Point(xPosition, yPosition);
graphic.DrawLine(Pens.Black, ptS, ptE);
}
else
{
line = null;
break;
}
}
//一页显示不完时自动重新调用此方法
if (line == null)
{
e.HasMorePages = true;
}
else
{
e.HasMorePages = false;
}
//每次打印完后countNum清0;
if (countNum >= printDt.Rows.Count)
{
countNum = ;
}
} } }
2、打印DataGridView
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Printing;
using System.Drawing;
using System.Windows.Forms; namespace WinSys.Common
{
public class Printer
{
private DataGridView dataview;
private PrintDocument printDoc;
//打印有效区域的宽度
int width;
int height;
int columns;
double Rate;
bool hasMorePage = false;
int currRow = ;
int rowHeight = ;
//打印页数
int PageNumber;
//当前打印页的行数
int pageSize = ;
//当前打印的页码
int PageIndex; private int PageWidth; //打印纸的宽度
private int PageHeight; //打印纸的高度
private int LeftMargin; //有效打印区距离打印纸的左边大小
private int TopMargin;//有效打印区距离打印纸的上面大小
private int RightMargin;//有效打印区距离打印纸的右边大小
private int BottomMargin;//有效打印区距离打印纸的下边大小 int rows; /**/
/// <summary>
/// 构造函数
/// </summary>
/// <param name="dataview">要打印的DateGridView</param>
/// <param name="printDoc">PrintDocument用于获取打印机的设置</param>
public Printer(DataGridView dataview, PrintDocument printDoc)
{
this.dataview = dataview;
this.printDoc = printDoc;
PageIndex = ;
//获取打印数据的具体行数
this.rows = dataview.RowCount; this.columns = dataview.ColumnCount;
//判断打印设置是否是横向打印
if (!printDoc.DefaultPageSettings.Landscape)
{ PageWidth = printDoc.DefaultPageSettings.PaperSize.Width;
PageHeight = printDoc.DefaultPageSettings.PaperSize.Height;
}
else
{
PageHeight = printDoc.DefaultPageSettings.PaperSize.Width;
PageWidth = printDoc.DefaultPageSettings.PaperSize.Height; }
LeftMargin = printDoc.DefaultPageSettings.Margins.Left;
TopMargin = printDoc.DefaultPageSettings.Margins.Top;
RightMargin = printDoc.DefaultPageSettings.Margins.Right;
BottomMargin = printDoc.DefaultPageSettings.Margins.Bottom; height = PageHeight - TopMargin - BottomMargin - ;
width = PageWidth - LeftMargin - RightMargin - ; double tempheight = height;
double temprowHeight = rowHeight;
while (true)
{
string temp = Convert.ToString(tempheight / Math.Round(temprowHeight, ));
int i = temp.IndexOf('.');
double tt = ;
if (i != -)
{
tt = Math.Round(Convert.ToDouble(temp.Substring(temp.IndexOf('.'))), );
}
if (tt <= 0.01)
{
rowHeight = Convert.ToInt32(temprowHeight);
break;
}
else
{
temprowHeight = temprowHeight + 0.01; }
}
pageSize = height / rowHeight;
if ((rows + ) <= pageSize)
{
pageSize = rows + ;
PageNumber = ;
}
else
{
PageNumber = rows / (pageSize - );
if (rows % (pageSize - ) != )
{
PageNumber = PageNumber + ;
}
}
} /**/
/// <summary>
/// 初始化打印
/// </summary>
private void InitPrint()
{
PageIndex = PageIndex + ;
if (PageIndex == PageNumber)
{
hasMorePage = false;
if (PageIndex != )
{
pageSize = rows % (pageSize - ) + ;
}
}
else
{
hasMorePage = true;
}
}
//打印头
private void DrawHeader(Graphics g)
{
Font font = new Font("宋体", , FontStyle.Bold);
int temptop = (rowHeight / ) + TopMargin + ;
int templeft = LeftMargin + ; for (int i = ; i < this.columns; i++)
{
string headString = this.dataview.Columns[i].HeaderText;
float fontHeight = g.MeasureString(headString, font).Height;
float fontwidth = g.MeasureString(headString, font).Width;
float temp = temptop - (fontHeight) / ;
g.DrawString(headString, font, Brushes.Black, new PointF(templeft, temp));
templeft = templeft + (int)(this.dataview.Columns[i].Width / Rate) + ;
}
}
//画表格
private void DrawTable(Graphics g)
{
Rectangle border = new Rectangle(LeftMargin, TopMargin, width, (pageSize) * rowHeight);
g.DrawRectangle(new Pen(Brushes.Black, ), border);
for (int i = ; i < pageSize; i++)
{
if (i != )
{
g.DrawLine(new Pen(Brushes.Black, ), new Point(LeftMargin + , (rowHeight * i) + TopMargin + ), new Point(width + LeftMargin, (rowHeight * i) + TopMargin + ));
}
else
{
g.DrawLine(new Pen(Brushes.Black, ), new Point(LeftMargin + , (rowHeight * i) + TopMargin + ), new Point(width + LeftMargin, (rowHeight * i) + TopMargin + ));
}
} //计算出列的总宽度和打印纸比率
Rate = Convert.ToDouble(GetDateViewWidth()) / Convert.ToDouble(width);
int tempLeft = LeftMargin + ;
int endY = (pageSize) * rowHeight + TopMargin;
for (int i = ; i < columns; i++)
{
tempLeft = tempLeft + + (int)(this.dataview.Columns[i - ].Width / Rate);
g.DrawLine(new Pen(Brushes.Black, ), new Point(tempLeft, TopMargin), new Point(tempLeft, endY));
}
}
/**/
/// <summary>
/// 获取打印的列的总宽度
/// </summary>
/// <returns></returns>
private int GetDateViewWidth()
{
int total = ;
for (int i = ; i < this.columns; i++)
{
total = total + this.dataview.Columns[i].Width;
}
return total;
} //打印行数据
private void DrawRows(Graphics g)
{ Font font = new Font("宋体", , FontStyle.Regular);
int temptop = (rowHeight / ) + TopMargin + + rowHeight; for (int i = currRow; i < pageSize + currRow - ; i++)
{
int templeft = LeftMargin + ;
for (int j = ; j < columns; j++)
{
string headString = this.dataview.Rows[i].Cells[j].Value.ToString();
float fontHeight = g.MeasureString(headString, font).Height;
float fontwidth = g.MeasureString(headString, font).Width;
float temp = temptop - (fontHeight) / ;
while (true)
{
if (fontwidth <= (int)(this.dataview.Columns[j].Width / Rate))
{
break;
}
else
{
headString = headString.Substring(, headString.Length - );
fontwidth = g.MeasureString(headString, font).Width;
}
}
g.DrawString(headString, font, Brushes.Black, new PointF(templeft, temp)); templeft = templeft + (int)(this.dataview.Columns[j].Width / Rate) + ;
} temptop = temptop + rowHeight;
}
currRow = pageSize + currRow - ;
} /**/
/// <summary>
/// 在PrintDocument中的PrintPage方法中调用
/// </summary>
/// <param name="g">传入PrintPage中PrintPageEventArgs中的Graphics</param>
/// <returns>是否还有打印页 有返回true,无则返回false</returns>
public bool Print(Graphics g)
{
InitPrint();
DrawTable(g);
DrawHeader(g);
DrawRows(g); //打印页码
string pagestr = PageIndex + " / " + PageNumber;
Font font = new Font("宋体", , FontStyle.Regular);
g.DrawString(pagestr, font, Brushes.Black, new PointF((PageWidth / ) - g.MeasureString(pagestr, font).Width, PageHeight - (BottomMargin / ) - g.MeasureString(pagestr, font).Height));
//打印查询的功能项名称
string temp = dataview.Tag.ToString() + " " + DateTime.Now.ToString("yyyy-MM-dd HH:mm");
g.DrawString(temp, font, Brushes.Black, new PointF(PageWidth - - g.MeasureString(temp, font).Width, PageHeight - - g.MeasureString(temp, font).Height));
return hasMorePage;
}
}
}