使用 e.HasMorePages 打印新页面
Printing new pages with e.HasMorePages
我有点困惑如何使用 HasMorePages
属性。我正在尝试根据 YPosition
方法打印更多页面,但它会导致打印页面无限循环。
这是我的代码:
private float YPosition()
{
return this.TopMargin + ((float)this.LinesCount * this.Font.GetHeight(this.Graphics) + (float)this.ImagesHeight);
}
private void TicketPrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.PageUnit = GraphicsUnit.Millimeter;
this.Graphics = e.Graphics;
foreach (Tuple<Object, LineTypes> tuple in this.Objects)
{
switch (tuple.Item2)
{
case LineTypes.LINE:
this.Graphics.DrawString((String)tuple.Item1, this.Font, this.SolidBrush, this.LeftMargin, this.YPosition(), new StringFormat());
this.LinesCount++;
break;
case LineTypes.IMAGE:
Image Image = (Image)tuple.Item1;
// Center Image, using PaperSize
Graphics GraphicsImage = Graphics.FromImage(Image);
RectangleF RectangleF = e.MarginBounds;
RectangleF.Offset(-e.PageSettings.HardMarginX, -e.PageSettings.HardMarginY);
float InchX = RectangleF.X / 100f + (RectangleF.Width / 100f - (float)Image.Width / GraphicsImage.DpiX) / 2f;
Int32 MillimeterX = (Int32)Math.Ceiling(InchX / 0.039370);
this.Graphics.DrawImage(Image, new Point((int)this.LeftMargin + (MillimeterX / 2), (int)this.YPosition()));
double a = (double)Image.Height / 58.0 * 15.0;
this.ImagesHeight += (int)Math.Round(a) + 3;
break;
}
if ((YPosition() * 4) >= e.PageSettings.PrintableArea.Height)
{
e.HasMorePages = true;
return;
}
else
{
e.HasMorePages = false;
}
}
}
YPosition
表示页面中每行或图像的高度。
如果处理完所有对象,如何防止无限循环打印并停止?
您需要使用 while 循环和 Enumerator. The enumerator keeps the state of which object you're handling and that is stored as a member on the form instance. Use the BeginPrint and EndPrint event of the PrintDocument class 来初始化和 clean-up 枚举器,而不是 for 循环。
// this is the variable that holds the enumerator instance
// once printing has started
IEnumerator<Tuple<Object, LineTypes>> ObjectsEnumerator;
// this is the event raised by printdocument at the start of printing
private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
this.ObjectsEnumerator = Objects.GetEnumerator();
}
因为我们现在有一个枚举器,PrintPage 实现将使用它。它调用 MoveNext and stores the result in HasMorePages
. The rest of the code is similar to what you had but make sure to keep the calculation of the position on the page local to the method. Don't (ab)use instance variables for that. Notice the call to Current
作为 while 循环中的第一条语句。
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int linesCount = 0;
float yPosition = 10;
// take the next item from the list by calling MoveNext
// and assign the outcome to e.HasMorePages
while(e.HasMorePages = this.ObjectsEnumerator.MoveNext())
{
var tuple = this.ObjectsEnumerator.Current;
switch (tuple.Item2)
{
case LineTypes.LINE:
// draw magic
e.Graphics.DrawString(tuple.Item1.ToString(), font, solidBrush, new PointF(10,yPosition));
yPosition += 300;
linesCount++;
break;
case LineTypes.IMAGE:
Image Image = (Image)tuple.Item1;
// e.Graphics.DrawImage(....);
// calculate new yPosition
yPosition += Image.Height;
break;
}
// if we reach the end of the page
if (yPosition >= e.PageSettings.PrintableArea.Height)
{
//we break out of the while loop
// e.HasMorePages is already set
break;
}
}
}
使用此代码,您可以迭代 collection,如果页面已满则跳出循环,并在没有更多项目可打印时停止迭代和打印。
如果打印完成,将调用 Endprint,其任务是 clean-up 枚举器。
private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
if (this.ObjectsEnumerator != null)
{
this.ObjectsEnumerator.Dispose();
this.ObjectsEnumerator = null;
}
}
我有点困惑如何使用 HasMorePages
属性。我正在尝试根据 YPosition
方法打印更多页面,但它会导致打印页面无限循环。
这是我的代码:
private float YPosition()
{
return this.TopMargin + ((float)this.LinesCount * this.Font.GetHeight(this.Graphics) + (float)this.ImagesHeight);
}
private void TicketPrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.PageUnit = GraphicsUnit.Millimeter;
this.Graphics = e.Graphics;
foreach (Tuple<Object, LineTypes> tuple in this.Objects)
{
switch (tuple.Item2)
{
case LineTypes.LINE:
this.Graphics.DrawString((String)tuple.Item1, this.Font, this.SolidBrush, this.LeftMargin, this.YPosition(), new StringFormat());
this.LinesCount++;
break;
case LineTypes.IMAGE:
Image Image = (Image)tuple.Item1;
// Center Image, using PaperSize
Graphics GraphicsImage = Graphics.FromImage(Image);
RectangleF RectangleF = e.MarginBounds;
RectangleF.Offset(-e.PageSettings.HardMarginX, -e.PageSettings.HardMarginY);
float InchX = RectangleF.X / 100f + (RectangleF.Width / 100f - (float)Image.Width / GraphicsImage.DpiX) / 2f;
Int32 MillimeterX = (Int32)Math.Ceiling(InchX / 0.039370);
this.Graphics.DrawImage(Image, new Point((int)this.LeftMargin + (MillimeterX / 2), (int)this.YPosition()));
double a = (double)Image.Height / 58.0 * 15.0;
this.ImagesHeight += (int)Math.Round(a) + 3;
break;
}
if ((YPosition() * 4) >= e.PageSettings.PrintableArea.Height)
{
e.HasMorePages = true;
return;
}
else
{
e.HasMorePages = false;
}
}
}
YPosition
表示页面中每行或图像的高度。
如果处理完所有对象,如何防止无限循环打印并停止?
您需要使用 while 循环和 Enumerator. The enumerator keeps the state of which object you're handling and that is stored as a member on the form instance. Use the BeginPrint and EndPrint event of the PrintDocument class 来初始化和 clean-up 枚举器,而不是 for 循环。
// this is the variable that holds the enumerator instance
// once printing has started
IEnumerator<Tuple<Object, LineTypes>> ObjectsEnumerator;
// this is the event raised by printdocument at the start of printing
private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
this.ObjectsEnumerator = Objects.GetEnumerator();
}
因为我们现在有一个枚举器,PrintPage 实现将使用它。它调用 MoveNext and stores the result in HasMorePages
. The rest of the code is similar to what you had but make sure to keep the calculation of the position on the page local to the method. Don't (ab)use instance variables for that. Notice the call to Current
作为 while 循环中的第一条语句。
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int linesCount = 0;
float yPosition = 10;
// take the next item from the list by calling MoveNext
// and assign the outcome to e.HasMorePages
while(e.HasMorePages = this.ObjectsEnumerator.MoveNext())
{
var tuple = this.ObjectsEnumerator.Current;
switch (tuple.Item2)
{
case LineTypes.LINE:
// draw magic
e.Graphics.DrawString(tuple.Item1.ToString(), font, solidBrush, new PointF(10,yPosition));
yPosition += 300;
linesCount++;
break;
case LineTypes.IMAGE:
Image Image = (Image)tuple.Item1;
// e.Graphics.DrawImage(....);
// calculate new yPosition
yPosition += Image.Height;
break;
}
// if we reach the end of the page
if (yPosition >= e.PageSettings.PrintableArea.Height)
{
//we break out of the while loop
// e.HasMorePages is already set
break;
}
}
}
使用此代码,您可以迭代 collection,如果页面已满则跳出循环,并在没有更多项目可打印时停止迭代和打印。
如果打印完成,将调用 Endprint,其任务是 clean-up 枚举器。
private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
if (this.ObjectsEnumerator != null)
{
this.ObjectsEnumerator.Dispose();
this.ObjectsEnumerator = null;
}
}