Search code examples
c#winformsresizepicturebox

C# handling the resizing of dynamically created picture boxes


With the following piece of code, I am dynamically creating and displaying picture boxes based on the number of screens I select in the combo box like in the bellow image:


enter image description here


This seems to work great, but the issue comes when i expand the application size, then the picture boxes dont expand correctly, like in the image bellow:


Enlarging the app:

enter image description here

Reducing the size of the app:

enter image description here

Here is the Method:

 private void CreatePictureBoxes(int num)
        {
            panelCameras.Controls.Clear();

            int spacing = 2;
            int numRows = (int)Math.Ceiling((double)num / 2);

            int pbWidth = (panelCameras.ClientSize.Width - (3 * spacing)) / 2;
            int pbHeight = (panelCameras.ClientSize.Height - ((numRows + 1) * spacing)) / numRows;

            if (num == 1)
            {
                pbWidth = panelCameras.ClientSize.Width - (2 * spacing);
                pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
            }
            else if (num == 2)
            {
                pbWidth = (panelCameras.ClientSize.Width - (2 * spacing)) / 2;
                pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
            }

            for (int i = 0; i < num; i++)
            {
                PictureBox pb = new PictureBox();
                pb.BackColor = Color.Black;
                pb.SizeMode = PictureBoxSizeMode.StretchImage;
                pb.Dock = DockStyle.None;
                pb.Anchor = AnchorStyles.None;
                pb.Location = new Point((i % 2) * (pbWidth + spacing) + spacing, (i / 2) * (pbHeight + spacing) + spacing);

                Label lbl = new Label();
                lbl.Text = (i + 1).ToString();
                lbl.ForeColor = Color.White;
                lbl.AutoSize = false;
                lbl.Dock = DockStyle.Fill;
                lbl.TextAlign = ContentAlignment.MiddleCenter;
                pb.Controls.Add(lbl);

                panelCameras.Controls.Add(pb);

                pb.Size = new Size(pbWidth, pbHeight);
                pb.Dock = DockStyle.None;
                pb.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;

                
            }
        }

My best attempt to fix this was to create an additional Method to handle the expansion of the app and call it at the end of the end of the CreatePictureBoxes method :


private void pb_Resize(object sender, EventArgs e)
        {
            PictureBox? pb = sender as PictureBox ?? null;

            if (pb != null)
            {
                int spacing = 10;
                int numRows = (int)Math.Ceiling((double)panelCameras.Controls.Count / 2);

                int pbWidth = (panelCameras.ClientSize.Width - (3 * spacing)) / 2;
                int pbHeight = (panelCameras.ClientSize.Height - ((numRows + 1) * spacing)) / numRows;

                if (panelCameras.Controls.Count == 1)
                {
                    pbWidth = panelCameras.ClientSize.Width - (2 * spacing);
                    pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
                }
                else if (panelCameras.Controls.Count == 2)
                {
                    pbWidth = (panelCameras.ClientSize.Width - (2 * spacing)) / 2;
                    pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
                }

                pb.Size = new Size(pbWidth, pbHeight);
                pb.Location = new Point((pb.TabIndex % 2) * (pbWidth + spacing) + spacing, (pb.TabIndex / 2) * (pbHeight + spacing) + spacing);
            }
        }

This somehow worked but I believe will cause more issues down the line and I dont believe it to be a good approach.

Would anyone know how I could handle the picture boxes sizes to be relative to the size of the application?

Thanks in advance!


Solution

  • I would separate the creation and the laying out of panels, like this:

    public Form1()
    {
        InitializeComponent();
    
        // ...
    
        panelCameras.Layout += panelCameras_Layout;
    }
    
    private void CreatePictureBoxes(int num)
    {
        panelCameras.Controls.Clear();
    
        for (int i = 0; i < num; i++)
        {
            PictureBox pb = new PictureBox();
            pb.BackColor = Color.Black;
            pb.SizeMode = PictureBoxSizeMode.StretchImage;
            pb.Dock = DockStyle.None;
            pb.Anchor = AnchorStyles.None;
    
            Label lbl = new Label();
            lbl.Text = (i + 1).ToString();
            lbl.ForeColor = Color.White;
            lbl.AutoSize = false;
            lbl.Dock = DockStyle.Fill;
            lbl.TextAlign = ContentAlignment.MiddleCenter;
            pb.Controls.Add(lbl);
    
            panelCameras.Controls.Add(pb);
        }
    }
    
    protected void panelCameras_Layout(object? sender, LayoutEventArgs levent)
    {
        var num = panelCameras.Controls.Count;
    
        for (var i = 0; i < num; ++i)
        {
            int spacing = 2;
            int numRows = (int)Math.Ceiling((double)num / 2);
    
            int pbWidth = (panelCameras.ClientSize.Width - (3 * spacing)) / 2;
            int pbHeight = (panelCameras.ClientSize.Height - ((numRows + 1) * spacing)) / numRows;
    
            if (num == 1)
            {
                pbWidth = panelCameras.ClientSize.Width - (2 * spacing);
                pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
            }
            else if (num == 2)
            {
                pbWidth = (panelCameras.ClientSize.Width - (2 * spacing)) / 2;
                pbHeight = panelCameras.ClientSize.Height - (2 * spacing);
            }
    
            var pb = panelCameras.Controls[i];
            pb.Location = new Point((i % 2) * (pbWidth + spacing) + spacing, (i / 2) * (pbHeight + spacing) + spacing);
            pb.Size = new Size(pbWidth, pbHeight);
        }
    }
    

    Note that I removed setting the Size and Location from CreatePictureBoxes and I also removed changing the Anchor style!