使用 e.HasMorePages 打印新页面

问题描述 投票:0回答:2

我有点困惑如何使用

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

如何防止打印无限循环并在处理完所有对象后停止?

c# .net winforms visual-studio drawing
2个回答
1
投票

您需要使用 while 循环和Enumerator,而不是 for 循环。枚举器保留您正在处理的对象的状态,并将其作为成员存储在表单实例上。使用 PrintDocument 类的 BeginPrintEndPrint 事件来初始化和清理枚举器。

// 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
中。代码的其余部分与您的代码类似,但请确保将页面上位置的计算保留在该方法的本地。不要为此使用实例变量。请注意,对
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;
        }
    }
}

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

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

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

0
投票

修复使用 HasMorePages 在 C# 中打印时的分页问题。 关于这段代码的解释:打印时可以添加很多行或者从数据库读取来查看分页的结果,比如我手动只在表中添加了两行,由于行数较少,所以没有分页。手动添加多行或将数据库中的信息插入到网格视图中。这是一个例子:

int currentPage = 1;
int rowsPerPage = 36; //Number of rows per page
int rowIndex = 0;

void pdoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
    try
    {
        int x = 5, y = 5; //Drawing start position
        int rowMargin = 0; //Spacing between lines

        dgvHesaab.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
        dgvHesaab.DefaultCellStyle.WrapMode = DataGridViewTriState.True;

        dgvHesaab.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
        dgvHesaab.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing; //Text with more lines in a row.
        dgvHesaab.ColumnHeadersHeight = 40; //40=row height. Text with more lines in a row.

        dgvHesaab.RightToLeft = RightToLeft.Yes;

        int rowCount = dgvHesaab.Rows.Count; //Get the number of rows
        int pageCount = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(rowCount) / Convert.ToDouble(rowsPerPage)));

        //Set header content of columns
        for (int j = this.dgvHesaab.Columns.Count - 1; j >= 0; j--)
        {
            Rectangle rect = new Rectangle(x, y, 132, dgvHesaab.Rows[0].Height); //132 = width in row
            StringFormat sf = new StringFormat();
            sf.LineAlignment = StringAlignment.Center;
            sf.Alignment = StringAlignment.Center;
            e.Graphics.FillRectangle(Brushes.LightGray, rect);
            e.Graphics.DrawRectangle(Pens.Black, rect);
            if (this.dgvHesaab.Columns[j].HeaderText != null)
            {
                e.Graphics.DrawString(this.dgvHesaab.Columns[j].HeaderText, SystemFonts.DefaultFont, Brushes.Black, rect, sf);
            }
            x += rect.Width;
        }

        x = 5;
        y += dgvHesaab.Rows[0].Height + rowMargin;
        //Set the content of the lines
        while (rowIndex < dgvHesaab.Rows.Count)
        {
            DataGridViewRow row = dgvHesaab.Rows[rowIndex];
            if (row.Cells[0].Value != null)
            {
                for (int j = this.dgvHesaab.Columns.Count - 1; j >= 0; j--)
                {
                    DataGridViewCell cell = row.Cells[j];
                    Rectangle rect = new Rectangle(x, y, 132, dgvHesaab.Rows[0].Height); //132 = width in row
                    StringFormat sf = new StringFormat();
                    sf.LineAlignment = StringAlignment.Center;
                    sf.Alignment = StringAlignment.Center;
                    e.Graphics.DrawRectangle(Pens.Black, rect);
                    if (cell.Value != null)
                    {
                        e.Graphics.DrawString(cell.Value.ToString(), new Font("Tahoma", 8, FontStyle.Bold), Brushes.Black, rect, sf);
                    }
                    x += rect.Width;
                }
                x = 5;
                y += dgvHesaab.Rows[0].Height + rowMargin;
            }
            rowIndex++;

            //Print a new page if necessary
            if (rowIndex % rowsPerPage == 0 || rowIndex == dgvHesaab.Rows.Count)
            {
                e.HasMorePages = (currentPage < pageCount);
                currentPage++;
                return;
            }
        }
    }
    catch (Exception)
    {

    }
}

   
private void btnAdd_Click(object sender, EventArgs e)
{
    try
    {
        //Begin , Adding a row to the gridView(dgvHesaab) 
        ///<summary>
        ///For example, the name of our Grid View is dgvHesaab
        ///Retrieving data from a database or manually inserting data for a row. 
        ///</summary>

        //add row 1
        dgvHesaab.Rows.Add(new object[]
        {
            "Row 1 : Item 1",
            "Row 1 : Item 2",
            "Row 1 : Item 3",
            "Row 1 : Item 4",
            "Row 1 : Item 5",
            "Row 1 : Item 6",
        });

        //add row 2
        dgvHesaab.Rows.Add(new object[]
        {
            "Row 2 : Item 1",
            "Row 2 : Item 2",
            "Row 2 : Item 3",
            "Row 2 : Item 4",
            "Row 2 : Item 5",
            "Row 2 : Item 6",
        });
        //End , Adding a row to the gridView(dgvHesaab)  

        dgvHesaab.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
        dgvHesaab.DefaultCellStyle.WrapMode = DataGridViewTriState.True;

        dgvHesaab.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
        dgvHesaab.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing; //Text with more lines in a row.
        dgvHesaab.ColumnHeadersHeight = 40; //40=row height. Text with more lines in a row.

        dgvHesaab.RightToLeft = RightToLeft.Yes;

        //Begin Print
        PrintDialog pDialog = new PrintDialog();
        pDialog.AllowCurrentPage = false;
        pDialog.AllowPrintToFile = false;
        pDialog.AllowSelection = false;
        pDialog.AllowSomePages = false;
        pDialog.PrintToFile = false;
        pDialog.ShowHelp = false;
        pDialog.ShowNetwork = false;
        if (pDialog.ShowDialog() == DialogResult.OK)
        {
            System.Drawing.Printing.PrintDocument pdoc = new System.Drawing.Printing.PrintDocument();
            pdoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pdoc_PrintPage);
            pdoc.DocumentName = "Print Title";
            pdoc.PrinterSettings = pDialog.PrinterSettings;
            pdoc.DefaultPageSettings = pDialog.PrinterSettings.DefaultPageSettings;
            pdoc.DefaultPageSettings.Margins = new System.Drawing.Printing.Margins(100, 100, 100, 100);
            pdoc.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("A4", 827, 1169);
            pdoc.DefaultPageSettings.Landscape = false; //Landscape
            //pdoc.PrinterSettings.Copies = 3;
            PrintPreviewDialog printPreviewDialog1 = new PrintPreviewDialog();
            printPreviewDialog1.Document = pdoc;
            pdoc.Print(); //No preview  
            //printPreviewDialog1.ShowDialog(); //printPreview
        }
        //End Print
    }
    catch (Exception)
    {

    }
}
© www.soinside.com 2019 - 2024. All rights reserved.