使用e.HasMorePages打印新页面 [英] Printing new pages with e.HasMorePages

查看:70
本文介绍了使用e.HasMorePages打印新页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点困惑如何使用 HasMorePages 属性.我试图通过 YPosition 方法来打印更多页面,但这会导致打印页面的无限循环.

I'm a little confused how I can use the HasMorePages property. I'm trying to print some page more depending by the YPosition method, but it causes an infinite loop of printing pages.

这是我的代码:

        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 表示页面中每行或图像的高度.

YPosition represent the height of each line or images in the pages.

如果处理了所有对象,如何防止打印的无休止循环和停止?

How can I prevent the endless loop of printing and stop if all Objects are handled?

推荐答案

您需要使用while循环和 BeginPrint

Instead of a for loop you need to use a while loop and an 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 to initialize and clean-up the enumerator.

// 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 ,并将结果存储在 HasMorePages 中.其余代码与您所拥有的相似,但是请确保将页面上位置的计算保持在该方法的本地.请勿为此使用实例变量.请注意对当前作为while循环中的第一条语句.

As we now have an enumerator the PrintPage implementation is going to use that. It calls 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 as the first statement in the while loop.

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;
        }
    }
}

使用此代码,您可以遍历集合,如果页面已满,则可以跳出循环,并在没有更多要打印的项目时停止迭代和打印.

With this code you can iterate over your collection, break out of the loop if the page is full and stop iterating and printing when there are no more items to print.

如果完成打印,将调用Endprint,其任务是清理枚举器.

If printing is done Endprint is called and its task is to clean-up the enumerator.

private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
    if (this.ObjectsEnumerator != null)
    {
        this.ObjectsEnumerator.Dispose();
        this.ObjectsEnumerator = null;
    }
}

这篇关于使用e.HasMorePages打印新页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆