所以对于应用层用着还不是很方便。最近做一个项目顺便就封装了一个调用默认打印机的类。虽说有几个小bug,但对于目前来说,已经满足需求了。以后不够了在来升级吧。
1,关于打印上下左右边距和纸张的高宽。以往都把这些写死到代码里面。既然是调用默认打印机,打印机的型号自然有差异。所以我就把这些配置放到app.config里面。但又怕每次打印都加载config影响效率。故此设计了个printpaper类。里面所有属性都是静态的。还有一个静态的构造方法。这样只有在程序开始运行加载一次config。之后就直接从内存读取了。
printpaper类
<appsettings>
<!--******************************连接字符串设置************************************-->
<add key="dbconnectionstr" value=" "/>
<!--********************************打印边界设置**********************************-->
<!--打印纸的距四个边界的距离,为空这表示默认为0,可以为负值-->
<!--与上边界距离-->
<add key="margintop" value=""/>
<!--与上边界距离-->
<add key="marginbottom" value=""/>
<!--与上边界距离-->
<add key="marginleft" value=""/>
<!--与上边界距离-->
<add key="marginright" value=""/>
<!--********************************打印纸大小设置**********************************-->
<!--打印纸张的大小,为空表示取默认值,不可以为负值 -->
<!--纸张的宽度-->
<add key="paperwidth" value=""/>
<!--纸张的高度-->
<add key="paperheight" value=""/>
<!--*******************************************************************************-->
</appsettings>
</configuration>
打印表格是自适应表格里面的文字最大的宽度。但如果表格里面确实列很少,没列的最大宽度又很小。打印完真整个表格没有页面的纸张宽。那会自动拉宽每一列的宽度。
打印的核心类printcore
private graphics graphic { set; get; }
/// 构造函数
/// </summary>
/// <param name="_printdoc">打印基础类</param>
/// <param name="_currentx">打印开始的x坐标,默认为0</param>
/// <param name="_currenty">打印开始的y坐标,默认为0</param>
public printcore(printdocument _printdoc, graphics _graphics, font _defaultfont, float _currentx = 0, float _currenty = 0)
{
this.printdoc = _printdoc;
this.currentx = _currentx;
this.currenty = _currenty;
this.defaultfont = _defaultfont;
this.graphic = _graphics;
this.defaultbrush = new solidbrush(color.black); //默认加粗黑色
this.iscenter = false;
//读取配置文件
printdocconfig(_printdoc);
error = printpaper.error;
}
private void printdocconfig(printdocument _printdoc)
{
_printdoc.defaultpagesettings.margins = new margins(printpaper.marginleft, printpaper.marginright, printpaper.margintop, printpaper.marginbottom);
//当paper配置的宽度和高度都大于0时,才配置。否则忽略
if (printpaper.width > 0 && printpaper.height > 0)
{
_printdoc.defaultpagesettings.papersize = new papersize("", printpaper.width, printpaper.height);
}
}
/// <summary>
/// 打印字符串,系统可以总动判断换行打印。
/// </summary>
/// <param name="prnstr">打印的字符串</param>
/// <param name="isprintline">打印完成后,是否换行,默认为true</param>
public void printstring(string prnstr, bool isprintline = true)
{
//打印字符串,根据字符串长度,和纸张宽度,高度等自动换行
sizef measure = graphic.measurestring(prnstr, defaultfont);
//如果x坐标不为0,或者打印的一行宽度大于纸张的宽度,则居中打印是没用的。不考虑打印
if (!iscenter || currentx != 0 || printdoc.defaultpagesettings.papersize.width < measure.width)
{
//计算打印这么多字要多少行
int rows = (int)math.ceiling(measure.width / (printdoc.defaultpagesettings.papersize.width - currentx));
//根据行,算出要打印的边界矩形框
graphic.drawstring(prnstr, defaultfont, defaultbrush, new rectangle((int)currentx, (int)currenty, (int)math.ceiling((printdoc.defaultpagesettings.papersize.width - currentx)), (int)math.ceiling((measure.height * rows))));
if (isprintline)//如果换行
{
currenty = currenty + measure.height * rows;
currentx = 0;
}
else
{
currenty = currenty + measure.height * (rows - 1);
currentx = (measure.width % (printdoc.defaultpagesettings.papersize.width - currentx)) + currentx;
}
}
else
{
//居中打印一行
//计算打印前的留白宽度
float blank = (printdoc.defaultpagesettings.papersize.width - measure.width) / 2.0f;
currentx = currentx + blank;
graphic.drawstring(prnstr, defaultfont, defaultbrush, currentx, currenty);
if (isprintline)//如果换行
{
currentx = 0;
currenty = currenty + measure.height;
}
else
{
currentx = currentx + measure.width;
}
}
}
/// <summary>
/// 打印表格,自适应没列的宽度
/// </summary>
/// <param name="prndgv"></param>
/// <param name="isprintline"></param>
public void printdatagridview(datagridview prndgv, font titlefont, brush titlebrush, color titlebackgroup, bool isprintline = true)
{
if (prndgv == null)
{
return;
}
prndgv.allowusertoaddrows = false;
//记录每一列的宽度
int[] columnwidths = new int[prndgv.columncount];
//******************取每列的最大宽度***********************
//先计算表头的宽度
for (int i = 0; i < prndgv.columncount; i++)
{
string celvalue = prndgv.columns[i].headertext;
sizef measure = graphic.measurestring(celvalue, titlefont);
columnwidths[i] = (int)math.ceiling(measure.width);//把打印表头所占的宽度 先放到columnwidths里面
}
//计算表中数据打印的最大宽度
for (int i = 0; i < prndgv.rows.count; i++)
{
for (int j = 0; j < prndgv.columncount; j++)
{
string celvalue = prndgv[j, i].value.tostring();
sizef measure = graphic.measurestring(celvalue, defaultfont);
if (columnwidths[j] < measure.width)//如果宽度小于打印宽度,则把长的打印宽度赋值给列宽
{
columnwidths[j] = (int)math.ceiling(measure.width);
}
}
}
//如果表格的宽度小于纸张的宽度,表格没列的宽度加大
int allcolumswidth = 0;
for (int i = 0; i < prndgv.columncount; i++)
{
allcolumswidth += columnwidths[i];//把打印表头所占的宽度 先放到columnwidths里面
}
if (allcolumswidth + prndgv.columncount < printpaper.width)
{
int columnaddwidth = (printpaper.width - allcolumswidth - prndgv.columncount) / prndgv.columncount;
for (int i = 0; i < prndgv.columncount; i++)
{
columnwidths[i] += columnaddwidth;
}
}
//*************************************************************
currentx = 0;
int titleheight = (int)math.ceiling(graphic.measurestring("1e{(汗", titlefont).height);
//打印表头
for (int i = 0; i < prndgv.columncount; i++)
{
string celvalue = prndgv.columns[i].headertext;
//打印背景
graphic.fillrectangle(new solidbrush(titlebackgroup), new rectangle((int)currentx, (int)currenty, columnwidths[i], titleheight));
//打印内容
graphic.drawstring(celvalue, titlefont, titlebrush, currentx, currenty);
//打印表格边框
graphic.drawrectangle(new pen(titlebrush), new rectangle((int)currentx, (int)currenty, columnwidths[i], titleheight));
currentx = currentx + columnwidths[i];
}
currentx = 0;
currenty = currenty + titleheight;
int contentheight = (int)math.ceiling(graphic.measurestring("1e{(汗", defaultfont).height);
//打印内容
for (int i = 0; i < prndgv.rows.count; i++)
{
for (int j = 0; j < prndgv.columncount; j++)
{
string celvalue = prndgv[j, i].value.tostring();//打印内容
graphic.drawstring(celvalue, defaultfont, defaultbrush, currentx, currenty);//打印表格边框
graphic.drawrectangle(new pen(defaultbrush), new rectangle((int)currentx, (int)currenty, columnwidths[j], contentheight));
currentx = currentx + columnwidths[j];
}
currentx = 0;
currenty = currenty + contentheight;
}
}
}
调用示例代码
总结:以上打印有两个小问题没有处理。一个是关于分页,一个是当表格的宽度过长,超过了页面的宽度,没有进行换行处理。
另附上源码
作者:bonker
如对本文有疑问, 点击进行留言回复!!
C# 对PDF文档加密、解密(基于Spire.Cloud.SDK for .NET)
Unity通用泛型单例设计模式(普通型和继承自MonoBehaviour)
网友评论