打印网页中特定内容
2007-04-28 11:53
405 查看
由于工作的需要,要求打印网页。而且是网页中的指定内容。有点多次一举“可是这就是客户的需求!!~”(某高人语)。收集了两个比较合适的解决方法。
首先是用JAVASCRIPT,以下是函数
<script language="javascript" type="text/javascript">
<!--
function Button3_onclick()
{
bdhtml=window.document.body.innerHTML;
sprnstr="<!--startprint-->";
eprnstr="<!--endprint-->";
prnhtml=bdhtml.substr(bdhtml.indexOf(sprnstr)+17);
prnhtml=prnhtml.substring(0,prnhtml.indexOf(eprnstr));
window.document.body.innerHTML=prnhtml;
window.print();
}
</script>
应用时把要打印的内容放到<!--startprint-->和<!--endprint-->之间。
二是C# documment类和print类的实现:
using System;
using System.ComponentModel;
using System.Collections;
using System.Drawing;
using System.Drawing.Printing;
using System.Globalization;
using System.IO;
using Print = System.Drawing.Printing.PrintDocument;
namespace Sanxing.NdtReprot.Internal
{
/**//// <summary>
/// 表示专用于大量文本打印的对象,该对象将输出至打印机。
/// </summary>
[Description("表示专用于大量文本打印的对象,该对象将输出至打印机。")]
internal sealed class TextPrintDocument : Print, IDisposable
{
私有变量#region 私有变量
private Font _printfont;
private Font _headerFooterFont;
private Pen _penHeaderFooterLine;
private PrintTextMode _printMode;
private bool _printLineNumbers;
private bool _printHeader;
private bool _printFooter;
private string _header;
private string _footer;
private TextReader _sr;
private ArrayList _buffer;
private bool _emptyBuffer;
private int _totalPageLines;
private int _currentPageLine;
private string _stringToPrint;
private int _currentPageNumber;
private int _currentLine;
private int _totalPrintedPages;
private const string DEFAULT_HEADER = "&n";
private const string DEFAULT_FOOTER = "&r&p";
private string[] _dateFormat =
{
"dddd", "ddd", "dd", "d", "D", "MMMM", "MMM", "MM", "m", "yyyy", "yy", "y", "f",
"F", "g", "G", "r", "s", "t", "T", "u", "U",
};
#endregion
属性#region 属性
/**//// <summary>
/// 设置要从中独取打印文本的 <see cref="Stream"/> 对象。
/// </summary>
[Category("内容"), Description("设置要从中独取打印文本的数据流。")]
internal Stream ContentStream
{
set
{
if(value != null)
_sr = new StreamReader(value);
}
}
/**//// <summary>
/// 获取或设置打印内容文本的字体。
/// </summary>
[Category("内容"), Description("获取或设置打印内容文本的字体。")]
internal Font BodyFont
{
get
{ return _printfont; }
set
{ _printfont = value; }
}
/**//// <summary>
/// 获取或设置打印页眉页脚文本的字体。
/// </summary>
[Category("内容"), Description("获取或设置打印页眉页脚文本的字体。")]
internal Font HeaderFooterFont
{
get
{ return _headerFooterFont; }
set
{ _headerFooterFont = value; }
}
/**//// <summary>
/// 获取或设置打印模式。
/// </summary>
[Category("内容"), Description("获取或设置打印模式。"), DefaultValue(PrintTextMode.WrapText)]
internal PrintTextMode PrintMode
{
get
{ return _printMode; }
set
{ _printMode = value; }
}
/**//// <summary>
/// 获取或设置每页打印的行数。
/// </summary>
[Category("内容"), Description("获取或设置每页打印的行数。")]
internal bool PrintLineNumber
{
get
{ return _printLineNumbers; }
set
{ _printLineNumbers = value; }
}
/**//// <summary>
/// 获取或设置一个值,该值指示是否打印页眉部分。
/// </summary>
[Category("内容"), Description("获取或设置一个值,该值指示是否打印页眉部分。"), DefaultValue(false)]
internal bool PrintHeader
{
get
{ return _printHeader; }
set
{ _printHeader = value; }
}
/**//// <summary>
/// 获取或设置一个值,该值指示是否打印页脚部分。
/// </summary>
[Category("内容"), Description("获取或设置一个值,该值指示是否打印页脚部分。"), DefaultValue(false)]
internal bool PrintFooter
{
get
{ return _printFooter; }
set
{ _printFooter = value; }
}
/**//// <summary>
/// 获取或设置要进行打印的文本。
/// </summary>
[Category("内容"), Description("获取或设置要进行打印的文本。")]
internal string Text
{
get
{ return _stringToPrint; }
set
{ _stringToPrint = value; }
}
/**//// <summary>
/// 获取或设置要打印在页眉部分的文本。
/// </summary>
[Description("获取或设置要打印在页眉部分的文本。"), DefaultValue(""), Category("内容")]
internal string Header
{
get
{ return _header; }
set
{ _header = value; }
}
/**//// <summary>
/// 获取或设置要打印在页脚部分的文本。
/// </summary>
[Category("内容"), Description("获取或设置要打印在页脚部分的文本。"), DefaultValue("")]
internal string Footer
{
get
{ return _footer; }
set
{ _footer = value; }
}
#endregion
构造器#region 构造器
/**//// <summary>
/// 使用默认值初始化 <b>TextPrintDocument</b> 类的新实例。
/// </summary>
public TextPrintDocument() : base()
{
_sr = null;
_stringToPrint = string.Empty;
_penHeaderFooterLine = Pens.Black;
_header = DEFAULT_HEADER;
_footer = DEFAULT_FOOTER;
}
/**//// <summary>
/// 使用内容流以及字体初始化<b>TextPrintDocument</b> 类的新实例。
/// </summary>
/// <param name="Stream"></param>
/// <param name="BodyFont"></param>
public TextPrintDocument(Stream Stream, Font BodyFont) :base()
{
if(Stream == null)
throw new ArgumentNullException("Stream");
_sr = new StreamReader(Stream);
if (BodyFont == null)
_printfont = new Font("宋体", 3.5f, FontStyle.Regular, GraphicsUnit.Millimeter);
else
_printfont = BodyFont;
_stringToPrint = string.Empty;
_penHeaderFooterLine = Pens.Black;
_header = DEFAULT_HEADER;
_footer = DEFAULT_FOOTER;
}
/**//// <summary>
///
/// </summary>
/// <param name="PrintText"></param>
/// <param name="BodyFont"></param>
public TextPrintDocument(string PrintText, Font BodyFont)
: base()
{
if(PrintText == null || PrintText == string.Empty)
throw new ArgumentNullException("PrintText");
_stringToPrint = PrintText;
_sr = null;
if (BodyFont == null)
_printfont = new Font("宋体", 3.5f, FontStyle.Regular, GraphicsUnit.Millimeter);
else
_printfont = BodyFont;
_penHeaderFooterLine = Pens.Black;
_header = DEFAULT_HEADER;
_footer = DEFAULT_FOOTER;
}
#endregion
方法#region 方法
/**//// <summary>
/// 在处理打印内容前,执行必要操作。
/// </summary>
/// <param name="e"></param>
protected override void OnBeginPrint(PrintEventArgs e)
{
base.OnBeginPrint(e);
if (_sr == null && _stringToPrint == string.Empty)
throw new InvalidOperationException("没有发现要进行打印处理的文档或数据流。");
// 检查是否有文本,有就生成读取器。
if (_stringToPrint != string.Empty)
_sr = new StringReader(_stringToPrint);
// 检查页眉页脚的字体
if (_headerFooterFont == null)
_headerFooterFont = _printfont;
_currentPageNumber = 0;
_totalPrintedPages = 0;
_currentLine = 1;
}
/**//// <summary>
/// 打印完毕后,执行必要操作。
/// </summary>
/// <param name="e"></param>
protected override void OnEndPrint(PrintEventArgs e)
{
base.OnEndPrint(e);
if(_sr != null)
_sr.Close();
_totalPrintedPages = _currentPageNumber;
}
/**//// <summary>
/// 在打印前,生成打印内容。
/// </summary>
/// <param name="e"></param>
protected override void OnPrintPage(PrintPageEventArgs e)
{
base.OnPrintPage(e);
Graphics gfx = e.Graphics;
PageSettings pageset = DefaultPageSettings; // 页面设置
float printAreaHeight = pageset.PaperSize.Height - (pageset.Margins.Top + pageset.Margins.Bottom);
float printAreaWidth = pageset.PaperSize.Width - (pageset.Margins.Left + pageset.Margins.Right);
float marginLeft = pageset.Margins.Left;
float marginTop = pageset.Margins.Top;
if(DefaultPageSettings.Landscape)
{
float tmp = printAreaHeight;
printAreaHeight = printAreaWidth;
printAreaWidth = tmp;
}
if(_buffer == null)
_buffer = new ArrayList(_totalPageLines);
float charHeight = _printfont.GetHeight(gfx);
float headerFooterCharHeight = _headerFooterFont.GetHeight(gfx);
float headerFooterHeight = headerFooterCharHeight + charHeight;
RectangleF rectHeader =
new RectangleF(marginLeft, marginTop, printAreaWidth, _printHeader ? headerFooterHeight : 0);
RectangleF rectFooter =
new RectangleF(marginLeft, marginTop + printAreaHeight, printAreaWidth,
_printFooter ? headerFooterHeight : 0);
if(_printHeader) // 检查是否要输出页头
DrawHeader(gfx, rectHeader);
_totalPageLines = Convert.ToInt32((printAreaHeight - rectFooter.Height - rectHeader.Height) / charHeight);
_currentPageLine = 0;
if(_stringToPrint == null)
_stringToPrint = GetNextLine();
while((_currentPageLine <= _totalPageLines) && (_stringToPrint != null))
{
float yPos = rectHeader.Bottom + (_currentPageLine * charHeight);
// Calculate printing rectangle area
RectangleF rectTextLine = new RectangleF(marginLeft, yPos, printAreaWidth, charHeight);
_stringToPrint = DrawTextLine(gfx, _stringToPrint, rectTextLine);
PutNextLine(_stringToPrint);
_currentPageLine++;
_currentLine++;
_stringToPrint = GetNextLine();
}
if(_printFooter)
DrawFooter(gfx, rectFooter);
_currentPageNumber++;
e.HasMorePages = HasMorePages();
}
#endregion
私有帮助器#region 私有帮助器
/**//// <summary>
/// 获取下一行的文本内容。
/// </summary>
/// <returns></returns>
private string GetNextLine()
{
string line = null;
if(_printMode == PrintTextMode.WrapText)
{
if(_buffer.Count == 0)
line = _sr.ReadLine();
else
{
line = (string) _buffer[0];
_buffer.RemoveAt(0);
}
}
else
{
if(_emptyBuffer)
{
if(_currentPageLine < _buffer.Count)
{
line = (string) _buffer[_currentPageLine];
_buffer[_currentPageLine] = null;
}
else
{
if(!HasBufferChars())
{
_buffer.Clear();
_emptyBuffer = false;
}
}
}
else
{
if(_currentPageLine <= _totalPageLines)
line = _sr.ReadLine();
_emptyBuffer = HasBufferChars();
if(line == null)
_emptyBuffer = HasBufferChars();
}
}
return line;
}
/**//// <summary>
/// 将处理过程推进到下一行。
/// </summary>
/// <param name="line"></param>
private void PutNextLine(string line)
{
if(_printMode == PrintTextMode.WrapText)
{
if(line.Length > 0)
{
if(_buffer.Count == 0)
_buffer.Add(line);
else
_buffer[0] = line;
}
}
else if(_printMode == PrintTextMode.BannerLike)
{
if(_currentPageLine < _buffer.Count)
_buffer[_currentPageLine] = line;
else
_buffer.Add(line);
}
}
private bool HasMorePages()
{
int moreChars = -1;
try
{
moreChars = _sr.Peek();
}
catch(Exception)
{}
return (moreChars != -1) || _emptyBuffer;
}
private bool HasBufferChars()
{
foreach(string str in _buffer)
{
if(str.Length > 0)
return true;
}
return false;
}
private string DrawTextLine(Graphics gfx, string text, RectangleF rectangle)
{
StringFormat fmt = new StringFormat();
if(_printLineNumbers)
{
Font fnLine = new Font(FontFamily.GenericMonospace, _printfont.Size);
string lineStr = String.Format("{0,4:G}", _currentLine);
SizeF szfLine = gfx.MeasureString(lineStr, fnLine, rectangle.Size, fmt);
gfx.DrawString(lineStr, fnLine, Brushes.Black, rectangle, fmt);
rectangle.Inflate(-(szfLine.Width + _printfont.Size), 0);
}
int charactersOnLine = GetLineBreakCharPosition(gfx, text, rectangle);
gfx.DrawString(text, _printfont, Brushes.Black, rectangle, fmt);
return text.Substring(charactersOnLine);
}
private int GetLineBreakCharPosition(Graphics gfx, string text, RectangleF rectangle)
{
StringFormat fmt = new StringFormat(StringFormatFlags.MeasureTrailingSpaces);
int charactersOnLine = 0;
int lines = 0;
SizeF sizeText = gfx.MeasureString(text, _printfont, rectangle.Size, fmt, out charactersOnLine, out lines);
string rem = text.Substring(0, charactersOnLine);
if(rem.EndsWith(" ") && (charactersOnLine < text.Length))
{
string noSpaces = rem.TrimEnd(new Char[]
{' '});
int nSpaces = rem.Length - noSpaces.Length;
SizeF sizeChunk =
gfx.MeasureString(noSpaces, _printfont, rectangle.Size, fmt, out charactersOnLine, out lines);
string spacer = String.Empty;
while(sizeChunk.Width <= rectangle.Width)
{
spacer += " ";
sizeChunk = gfx.MeasureString(noSpaces + spacer, _printfont, new PointF(0, 0), fmt);
}
charactersOnLine += spacer.Length - ((sizeChunk.Width > rectangle.Width) ? 1 : 0);
}
return charactersOnLine;
}
/**//// <summary>
/// 打印页眉。
/// </summary>
/// <param name="gfx"></param>
/// <param name="rectangle"></param>
private void DrawHeader(Graphics gfx, RectangleF rectangle)
{
StringFormat fmtHeader = new StringFormat();
string header = MakeHeaderFooterString(Header, ref fmtHeader);
gfx.DrawString(header, _headerFooterFont, Brushes.Black, rectangle, fmtHeader);
float yPos = rectangle.Top + (_headerFooterFont.GetHeight(gfx) + 2);
if(yPos <= rectangle.Bottom)
gfx.DrawLine(_penHeaderFooterLine, rectangle.Left, yPos, rectangle.Right, yPos);
}
/**//// <summary>
/// 打印页脚。
/// </summary>
/// <param name="gfx"></param>
/// <param name="rectangle"></param>
private void DrawFooter(Graphics gfx, RectangleF rectangle)
{
StringFormat fmtHeader = new StringFormat();
string header = MakeHeaderFooterString(Footer, ref fmtHeader);
fmtHeader.LineAlignment |= StringAlignment.Far;
gfx.DrawString(header, _headerFooterFont, Brushes.Black, rectangle, fmtHeader);
float yPos = rectangle.Bottom - (_headerFooterFont.GetHeight(gfx) + 2);
if(yPos >= rectangle.Top)
gfx.DrawLine(_penHeaderFooterLine, rectangle.Left, yPos, rectangle.Right, yPos);
}
private string MakeHeaderFooterString(string template, ref StringFormat format)
{
string headerFooter = template;
int ix = headerFooter.IndexOf("&l");
if(ix != -1)
{
format.Alignment = StringAlignment.Near;
headerFooter = headerFooter.Remove(ix, 2);
}
ix = headerFooter.IndexOf("&r");
if(ix != -1)
{
format.Alignment = StringAlignment.Far;
headerFooter = headerFooter.Remove(ix, 2);
}
ix = headerFooter.IndexOf("&c");
if(ix != -1)
{
format.Alignment = StringAlignment.Center;
headerFooter = headerFooter.Remove(ix, 2);
}
headerFooter = headerFooter.Replace("&p", (_currentPageNumber + 1).ToString());
headerFooter = headerFooter.Replace("&n", DocumentName);
DateTime dt = DateTime.Now;
ix = 0;
while((ix = headerFooter.IndexOf("%")) != -1)
{
bool found = false;
for(int i = 0; i < _dateFormat.Length; i++)
{
string fmt = "%" + _dateFormat[i];
if(headerFooter.Substring(ix, fmt.Length) == fmt)
{
string date = dt.ToString(_dateFormat[i], DateTimeFormatInfo.InvariantInfo);
headerFooter = headerFooter.Remove(ix, fmt.Length);
headerFooter = headerFooter.Insert(ix, date);
found = true;
break;
}
}
if(!found)
headerFooter = headerFooter.Remove(ix, 1);
}
return headerFooter;
}
#endregion
IDisposable 成员#region IDisposable 成员
/**//// <summary>
/// 移除由 <b>TextPrintDocument</b> 使用的所有托管资源。
/// </summary>
public new void Dispose()
{
Dispose(true);
}
/**//// <summary>
///
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if(disposing)
{
lock(this)
{
if (_sr != null)
_sr.Dispose();
}
GC.SuppressFinalize(true);
}
base.Dispose(disposing);
}
/**//// <summary>
/// 供 <see cref="GC"/> 使用的清理托管资源的方法。
/// </summary>
~TextPrintDocument()
{
Dispose(false);
}
#endregion
}
/**//// <summary>
/// 指定打印文本的模式。
/// </summary>
internal enum PrintTextMode
{
/**//// <summary>
/// 换行文本。
/// </summary>
WrapText,
Truncate,
BannerLike
}
}
首先是用JAVASCRIPT,以下是函数
<script language="javascript" type="text/javascript">
<!--
function Button3_onclick()
{
bdhtml=window.document.body.innerHTML;
sprnstr="<!--startprint-->";
eprnstr="<!--endprint-->";
prnhtml=bdhtml.substr(bdhtml.indexOf(sprnstr)+17);
prnhtml=prnhtml.substring(0,prnhtml.indexOf(eprnstr));
window.document.body.innerHTML=prnhtml;
window.print();
}
</script>
应用时把要打印的内容放到<!--startprint-->和<!--endprint-->之间。
二是C# documment类和print类的实现:
using System;
using System.ComponentModel;
using System.Collections;
using System.Drawing;
using System.Drawing.Printing;
using System.Globalization;
using System.IO;
using Print = System.Drawing.Printing.PrintDocument;
namespace Sanxing.NdtReprot.Internal
{
/**//// <summary>
/// 表示专用于大量文本打印的对象,该对象将输出至打印机。
/// </summary>
[Description("表示专用于大量文本打印的对象,该对象将输出至打印机。")]
internal sealed class TextPrintDocument : Print, IDisposable
{
私有变量#region 私有变量
private Font _printfont;
private Font _headerFooterFont;
private Pen _penHeaderFooterLine;
private PrintTextMode _printMode;
private bool _printLineNumbers;
private bool _printHeader;
private bool _printFooter;
private string _header;
private string _footer;
private TextReader _sr;
private ArrayList _buffer;
private bool _emptyBuffer;
private int _totalPageLines;
private int _currentPageLine;
private string _stringToPrint;
private int _currentPageNumber;
private int _currentLine;
private int _totalPrintedPages;
private const string DEFAULT_HEADER = "&n";
private const string DEFAULT_FOOTER = "&r&p";
private string[] _dateFormat =
{
"dddd", "ddd", "dd", "d", "D", "MMMM", "MMM", "MM", "m", "yyyy", "yy", "y", "f",
"F", "g", "G", "r", "s", "t", "T", "u", "U",
};
#endregion
属性#region 属性
/**//// <summary>
/// 设置要从中独取打印文本的 <see cref="Stream"/> 对象。
/// </summary>
[Category("内容"), Description("设置要从中独取打印文本的数据流。")]
internal Stream ContentStream
{
set
{
if(value != null)
_sr = new StreamReader(value);
}
}
/**//// <summary>
/// 获取或设置打印内容文本的字体。
/// </summary>
[Category("内容"), Description("获取或设置打印内容文本的字体。")]
internal Font BodyFont
{
get
{ return _printfont; }
set
{ _printfont = value; }
}
/**//// <summary>
/// 获取或设置打印页眉页脚文本的字体。
/// </summary>
[Category("内容"), Description("获取或设置打印页眉页脚文本的字体。")]
internal Font HeaderFooterFont
{
get
{ return _headerFooterFont; }
set
{ _headerFooterFont = value; }
}
/**//// <summary>
/// 获取或设置打印模式。
/// </summary>
[Category("内容"), Description("获取或设置打印模式。"), DefaultValue(PrintTextMode.WrapText)]
internal PrintTextMode PrintMode
{
get
{ return _printMode; }
set
{ _printMode = value; }
}
/**//// <summary>
/// 获取或设置每页打印的行数。
/// </summary>
[Category("内容"), Description("获取或设置每页打印的行数。")]
internal bool PrintLineNumber
{
get
{ return _printLineNumbers; }
set
{ _printLineNumbers = value; }
}
/**//// <summary>
/// 获取或设置一个值,该值指示是否打印页眉部分。
/// </summary>
[Category("内容"), Description("获取或设置一个值,该值指示是否打印页眉部分。"), DefaultValue(false)]
internal bool PrintHeader
{
get
{ return _printHeader; }
set
{ _printHeader = value; }
}
/**//// <summary>
/// 获取或设置一个值,该值指示是否打印页脚部分。
/// </summary>
[Category("内容"), Description("获取或设置一个值,该值指示是否打印页脚部分。"), DefaultValue(false)]
internal bool PrintFooter
{
get
{ return _printFooter; }
set
{ _printFooter = value; }
}
/**//// <summary>
/// 获取或设置要进行打印的文本。
/// </summary>
[Category("内容"), Description("获取或设置要进行打印的文本。")]
internal string Text
{
get
{ return _stringToPrint; }
set
{ _stringToPrint = value; }
}
/**//// <summary>
/// 获取或设置要打印在页眉部分的文本。
/// </summary>
[Description("获取或设置要打印在页眉部分的文本。"), DefaultValue(""), Category("内容")]
internal string Header
{
get
{ return _header; }
set
{ _header = value; }
}
/**//// <summary>
/// 获取或设置要打印在页脚部分的文本。
/// </summary>
[Category("内容"), Description("获取或设置要打印在页脚部分的文本。"), DefaultValue("")]
internal string Footer
{
get
{ return _footer; }
set
{ _footer = value; }
}
#endregion
构造器#region 构造器
/**//// <summary>
/// 使用默认值初始化 <b>TextPrintDocument</b> 类的新实例。
/// </summary>
public TextPrintDocument() : base()
{
_sr = null;
_stringToPrint = string.Empty;
_penHeaderFooterLine = Pens.Black;
_header = DEFAULT_HEADER;
_footer = DEFAULT_FOOTER;
}
/**//// <summary>
/// 使用内容流以及字体初始化<b>TextPrintDocument</b> 类的新实例。
/// </summary>
/// <param name="Stream"></param>
/// <param name="BodyFont"></param>
public TextPrintDocument(Stream Stream, Font BodyFont) :base()
{
if(Stream == null)
throw new ArgumentNullException("Stream");
_sr = new StreamReader(Stream);
if (BodyFont == null)
_printfont = new Font("宋体", 3.5f, FontStyle.Regular, GraphicsUnit.Millimeter);
else
_printfont = BodyFont;
_stringToPrint = string.Empty;
_penHeaderFooterLine = Pens.Black;
_header = DEFAULT_HEADER;
_footer = DEFAULT_FOOTER;
}
/**//// <summary>
///
/// </summary>
/// <param name="PrintText"></param>
/// <param name="BodyFont"></param>
public TextPrintDocument(string PrintText, Font BodyFont)
: base()
{
if(PrintText == null || PrintText == string.Empty)
throw new ArgumentNullException("PrintText");
_stringToPrint = PrintText;
_sr = null;
if (BodyFont == null)
_printfont = new Font("宋体", 3.5f, FontStyle.Regular, GraphicsUnit.Millimeter);
else
_printfont = BodyFont;
_penHeaderFooterLine = Pens.Black;
_header = DEFAULT_HEADER;
_footer = DEFAULT_FOOTER;
}
#endregion
方法#region 方法
/**//// <summary>
/// 在处理打印内容前,执行必要操作。
/// </summary>
/// <param name="e"></param>
protected override void OnBeginPrint(PrintEventArgs e)
{
base.OnBeginPrint(e);
if (_sr == null && _stringToPrint == string.Empty)
throw new InvalidOperationException("没有发现要进行打印处理的文档或数据流。");
// 检查是否有文本,有就生成读取器。
if (_stringToPrint != string.Empty)
_sr = new StringReader(_stringToPrint);
// 检查页眉页脚的字体
if (_headerFooterFont == null)
_headerFooterFont = _printfont;
_currentPageNumber = 0;
_totalPrintedPages = 0;
_currentLine = 1;
}
/**//// <summary>
/// 打印完毕后,执行必要操作。
/// </summary>
/// <param name="e"></param>
protected override void OnEndPrint(PrintEventArgs e)
{
base.OnEndPrint(e);
if(_sr != null)
_sr.Close();
_totalPrintedPages = _currentPageNumber;
}
/**//// <summary>
/// 在打印前,生成打印内容。
/// </summary>
/// <param name="e"></param>
protected override void OnPrintPage(PrintPageEventArgs e)
{
base.OnPrintPage(e);
Graphics gfx = e.Graphics;
PageSettings pageset = DefaultPageSettings; // 页面设置
float printAreaHeight = pageset.PaperSize.Height - (pageset.Margins.Top + pageset.Margins.Bottom);
float printAreaWidth = pageset.PaperSize.Width - (pageset.Margins.Left + pageset.Margins.Right);
float marginLeft = pageset.Margins.Left;
float marginTop = pageset.Margins.Top;
if(DefaultPageSettings.Landscape)
{
float tmp = printAreaHeight;
printAreaHeight = printAreaWidth;
printAreaWidth = tmp;
}
if(_buffer == null)
_buffer = new ArrayList(_totalPageLines);
float charHeight = _printfont.GetHeight(gfx);
float headerFooterCharHeight = _headerFooterFont.GetHeight(gfx);
float headerFooterHeight = headerFooterCharHeight + charHeight;
RectangleF rectHeader =
new RectangleF(marginLeft, marginTop, printAreaWidth, _printHeader ? headerFooterHeight : 0);
RectangleF rectFooter =
new RectangleF(marginLeft, marginTop + printAreaHeight, printAreaWidth,
_printFooter ? headerFooterHeight : 0);
if(_printHeader) // 检查是否要输出页头
DrawHeader(gfx, rectHeader);
_totalPageLines = Convert.ToInt32((printAreaHeight - rectFooter.Height - rectHeader.Height) / charHeight);
_currentPageLine = 0;
if(_stringToPrint == null)
_stringToPrint = GetNextLine();
while((_currentPageLine <= _totalPageLines) && (_stringToPrint != null))
{
float yPos = rectHeader.Bottom + (_currentPageLine * charHeight);
// Calculate printing rectangle area
RectangleF rectTextLine = new RectangleF(marginLeft, yPos, printAreaWidth, charHeight);
_stringToPrint = DrawTextLine(gfx, _stringToPrint, rectTextLine);
PutNextLine(_stringToPrint);
_currentPageLine++;
_currentLine++;
_stringToPrint = GetNextLine();
}
if(_printFooter)
DrawFooter(gfx, rectFooter);
_currentPageNumber++;
e.HasMorePages = HasMorePages();
}
#endregion
私有帮助器#region 私有帮助器
/**//// <summary>
/// 获取下一行的文本内容。
/// </summary>
/// <returns></returns>
private string GetNextLine()
{
string line = null;
if(_printMode == PrintTextMode.WrapText)
{
if(_buffer.Count == 0)
line = _sr.ReadLine();
else
{
line = (string) _buffer[0];
_buffer.RemoveAt(0);
}
}
else
{
if(_emptyBuffer)
{
if(_currentPageLine < _buffer.Count)
{
line = (string) _buffer[_currentPageLine];
_buffer[_currentPageLine] = null;
}
else
{
if(!HasBufferChars())
{
_buffer.Clear();
_emptyBuffer = false;
}
}
}
else
{
if(_currentPageLine <= _totalPageLines)
line = _sr.ReadLine();
_emptyBuffer = HasBufferChars();
if(line == null)
_emptyBuffer = HasBufferChars();
}
}
return line;
}
/**//// <summary>
/// 将处理过程推进到下一行。
/// </summary>
/// <param name="line"></param>
private void PutNextLine(string line)
{
if(_printMode == PrintTextMode.WrapText)
{
if(line.Length > 0)
{
if(_buffer.Count == 0)
_buffer.Add(line);
else
_buffer[0] = line;
}
}
else if(_printMode == PrintTextMode.BannerLike)
{
if(_currentPageLine < _buffer.Count)
_buffer[_currentPageLine] = line;
else
_buffer.Add(line);
}
}
private bool HasMorePages()
{
int moreChars = -1;
try
{
moreChars = _sr.Peek();
}
catch(Exception)
{}
return (moreChars != -1) || _emptyBuffer;
}
private bool HasBufferChars()
{
foreach(string str in _buffer)
{
if(str.Length > 0)
return true;
}
return false;
}
private string DrawTextLine(Graphics gfx, string text, RectangleF rectangle)
{
StringFormat fmt = new StringFormat();
if(_printLineNumbers)
{
Font fnLine = new Font(FontFamily.GenericMonospace, _printfont.Size);
string lineStr = String.Format("{0,4:G}", _currentLine);
SizeF szfLine = gfx.MeasureString(lineStr, fnLine, rectangle.Size, fmt);
gfx.DrawString(lineStr, fnLine, Brushes.Black, rectangle, fmt);
rectangle.Inflate(-(szfLine.Width + _printfont.Size), 0);
}
int charactersOnLine = GetLineBreakCharPosition(gfx, text, rectangle);
gfx.DrawString(text, _printfont, Brushes.Black, rectangle, fmt);
return text.Substring(charactersOnLine);
}
private int GetLineBreakCharPosition(Graphics gfx, string text, RectangleF rectangle)
{
StringFormat fmt = new StringFormat(StringFormatFlags.MeasureTrailingSpaces);
int charactersOnLine = 0;
int lines = 0;
SizeF sizeText = gfx.MeasureString(text, _printfont, rectangle.Size, fmt, out charactersOnLine, out lines);
string rem = text.Substring(0, charactersOnLine);
if(rem.EndsWith(" ") && (charactersOnLine < text.Length))
{
string noSpaces = rem.TrimEnd(new Char[]
{' '});
int nSpaces = rem.Length - noSpaces.Length;
SizeF sizeChunk =
gfx.MeasureString(noSpaces, _printfont, rectangle.Size, fmt, out charactersOnLine, out lines);
string spacer = String.Empty;
while(sizeChunk.Width <= rectangle.Width)
{
spacer += " ";
sizeChunk = gfx.MeasureString(noSpaces + spacer, _printfont, new PointF(0, 0), fmt);
}
charactersOnLine += spacer.Length - ((sizeChunk.Width > rectangle.Width) ? 1 : 0);
}
return charactersOnLine;
}
/**//// <summary>
/// 打印页眉。
/// </summary>
/// <param name="gfx"></param>
/// <param name="rectangle"></param>
private void DrawHeader(Graphics gfx, RectangleF rectangle)
{
StringFormat fmtHeader = new StringFormat();
string header = MakeHeaderFooterString(Header, ref fmtHeader);
gfx.DrawString(header, _headerFooterFont, Brushes.Black, rectangle, fmtHeader);
float yPos = rectangle.Top + (_headerFooterFont.GetHeight(gfx) + 2);
if(yPos <= rectangle.Bottom)
gfx.DrawLine(_penHeaderFooterLine, rectangle.Left, yPos, rectangle.Right, yPos);
}
/**//// <summary>
/// 打印页脚。
/// </summary>
/// <param name="gfx"></param>
/// <param name="rectangle"></param>
private void DrawFooter(Graphics gfx, RectangleF rectangle)
{
StringFormat fmtHeader = new StringFormat();
string header = MakeHeaderFooterString(Footer, ref fmtHeader);
fmtHeader.LineAlignment |= StringAlignment.Far;
gfx.DrawString(header, _headerFooterFont, Brushes.Black, rectangle, fmtHeader);
float yPos = rectangle.Bottom - (_headerFooterFont.GetHeight(gfx) + 2);
if(yPos >= rectangle.Top)
gfx.DrawLine(_penHeaderFooterLine, rectangle.Left, yPos, rectangle.Right, yPos);
}
private string MakeHeaderFooterString(string template, ref StringFormat format)
{
string headerFooter = template;
int ix = headerFooter.IndexOf("&l");
if(ix != -1)
{
format.Alignment = StringAlignment.Near;
headerFooter = headerFooter.Remove(ix, 2);
}
ix = headerFooter.IndexOf("&r");
if(ix != -1)
{
format.Alignment = StringAlignment.Far;
headerFooter = headerFooter.Remove(ix, 2);
}
ix = headerFooter.IndexOf("&c");
if(ix != -1)
{
format.Alignment = StringAlignment.Center;
headerFooter = headerFooter.Remove(ix, 2);
}
headerFooter = headerFooter.Replace("&p", (_currentPageNumber + 1).ToString());
headerFooter = headerFooter.Replace("&n", DocumentName);
DateTime dt = DateTime.Now;
ix = 0;
while((ix = headerFooter.IndexOf("%")) != -1)
{
bool found = false;
for(int i = 0; i < _dateFormat.Length; i++)
{
string fmt = "%" + _dateFormat[i];
if(headerFooter.Substring(ix, fmt.Length) == fmt)
{
string date = dt.ToString(_dateFormat[i], DateTimeFormatInfo.InvariantInfo);
headerFooter = headerFooter.Remove(ix, fmt.Length);
headerFooter = headerFooter.Insert(ix, date);
found = true;
break;
}
}
if(!found)
headerFooter = headerFooter.Remove(ix, 1);
}
return headerFooter;
}
#endregion
IDisposable 成员#region IDisposable 成员
/**//// <summary>
/// 移除由 <b>TextPrintDocument</b> 使用的所有托管资源。
/// </summary>
public new void Dispose()
{
Dispose(true);
}
/**//// <summary>
///
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if(disposing)
{
lock(this)
{
if (_sr != null)
_sr.Dispose();
}
GC.SuppressFinalize(true);
}
base.Dispose(disposing);
}
/**//// <summary>
/// 供 <see cref="GC"/> 使用的清理托管资源的方法。
/// </summary>
~TextPrintDocument()
{
Dispose(false);
}
#endregion
}
/**//// <summary>
/// 指定打印文本的模式。
/// </summary>
internal enum PrintTextMode
{
/**//// <summary>
/// 换行文本。
/// </summary>
WrapText,
Truncate,
BannerLike
}
}
相关文章推荐
- javascript打印网页的特定内容(以打印table为例)
- 打印网页中特定内容的实现方法-----网络收集
- 打印网页中特定内容的实现方法-----网络收集
- 如何去掉打印网页时自带的网址以及页码等内容
- window.print()打印网页中指定内容的实现方法
- 在HTML网页上打印需要的内容,JS代…
- js print打印网页指定区域内容的简单实例
- 使用javascript对网页的部分内容进行打印
- [自用门户]js 打印网页中指定的部分内容和范围
- 【网页打印】网页打印时内容没有居中显示解决方法
- js window.print实现打印特定控件或内容
- 用window.print()函数打印网页指定区域的内容
- 用window.print()函数打印网页指定区域的内容
- ASP.NET网页打印(只打印相关内容/自写功能)
- 使用网页代码“截取”功能,打印页面某段定义区域内容
- Javascript打印网页部分内容的脚本
- 使用网页代码“截取”功能,打印页面某段定义区域内容
- 如何去掉打印网页时自带的网址以及页码等内容
- 使用javascript去掉打印网页时页眉与页脚的内容
- 用window.print()函数打印网页指定区域的内容