Search code examples
c#printingflowlayoutpanel

How to print all the Images of PictureBoxes in a FlowLayoutPanel


I'm struggling to print all the images of PictureBox-es which are hosted by a FlowLayoutPanel container.

I've have tried this code but I'm getting an exception:

private void PrintAllImages()
{
    imagesToPrintCount = flowLayoutPanel1.Controls.Count;
    PrintDocument doc = new PrintDocument();
    doc.PrintPage += Document_PrintPage;
    PrintDialog dialog = new PrintDialog();
    dialog.Document = doc;

    if (dialog.ShowDialog() == DialogResult.OK)
        doc.Print();
}

private void Document_PrintPage(object sender, PrintPageEventArgs e)
{
    e.Graphics.DrawImage(GetNextImage(), e.MarginBounds);
    e.HasMorePages = imagesToPrintCount > 0;
}

private Image GetNextImage()
{
    //this line I get the error
    PictureBox pictureBox = (PictureBox)flowLayoutPanel2.Controls[flowLayoutPanel2.Controls.Count - imagesToPrintCount];

    imagesToPrintCount--;
    return pictureBox.Image;

}

The Exception:

System.ArgumentOutOfRangeException: 'Index -2 is out of range. Parameter name: index'


Solution

  • You can simplify the task by using the Queue class.

    • Create a new Queue<Image>.
    • Get the PictureBox-es from the FlowLayoutPanel and Enqueue their images.
    • In the PrintPage event, Dequeue the next image and draw it until the queue is empty.

    I'll shrink your code to the PrintAllImages() method as follows:

    using System.Collections.Generic;
    using System.Drawing.Printing;
    //...
    
    private void PrintAllImages()
    {
        var queue = new Queue<Image>();
    
        flowLayoutPanel2.Controls.OfType<PictureBox>().Where(p => p.Image != null)
            .ToList().ForEach(p => queue.Enqueue(p.Image));
    
        if (queue.Count == 0) return;
    
        using (var doc = new PrintDocument())
        using (var pd = new PrintDialog())
        {
            pd.Document = doc;
            if(pd.ShowDialog() == DialogResult.OK)
            {
                doc.PrintPage += (s, e) =>
                    {
                        e.Graphics.DrawImage(queue.Dequeue(), e.MarginBounds);
                        e.HasMorePages = queue.Count > 0;
                    };
                pd.Document.Print();
            }
        }
    }
    //...