所以對于應用層用著還不是很方便。最近做一個項目順便就封裝了一個調用默認打印機的類。雖說有幾個小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;
}
}
}
調用示例代碼
總結:以上打印有兩個小問題沒有處理。一個是關于分頁,一個是當表格的寬度過長,超過了頁面的寬度,沒有進行換行處理。
另附上源碼 winfrom_mrdyj_jb51net
作者:Bonker
新聞熱點
疑難解答