0

Exception:

Controls created on one thread cannot be parented to a control on a different thread.

This thread explains nicely how to do it on the instance of the class, (uses this keyword) statics don't refer to the instance so I'm out of luck there.

The class where the calling function is not static, and is calling this function like this...

DrawPlane.drawPlane(ref pnl);

Also in the calling class, I used this naughty property to attempt to mitigate illegal cross-threading...

CheckForIllegalCrossThreadCalls = false;

The full class:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Skork.ui {
class DrawPlane {

    private static int numX;
    private static int numY;
    private static BackgroundWorker bg;

    static DrawPlane() {
        numX = 0;
        numY = 0;
        bg = new BackgroundWorker();

    }      

    public static void drawPlane(ref Panel plane) {           
        bg.DoWork += Bg_DoWork;
        bg.RunWorkerAsync(plane);
    }

    private static void Bg_DoWork(object sender, DoWorkEventArgs e) {
        Panel plane = new Panel();

        if (e.Argument is Panel) {
            plane = (Panel) e.Argument;
        } else {
            throw new Exception("Object is not a panel!!" +
                e.Argument.ToString());
        }


        plane.Controls.Clear();
        numX = 0;
        numY = 0;

        Random rnd = new Random();
        Size sz = plane.Size;
        Point temp = new Point(0, 0);
        const int sizeUnit = 4; // 4 pixels wide
        bg.DoWork += Bg_DoWork; // add event
        int x = 0;

        for (int y = 0; y < sz.Height; y += sizeUnit * sizeUnit) {
            temp.X = 0;
            numY++;

            for (x = 0; x < sz.Width; x += sizeUnit * (sizeUnit / 2)) {

                if (x + temp.X < sz.Width) {
                    PictureBox unit = new PictureBox();
                    rnd = new Random(rnd.Next());

                    unit.Size = new Size(sizeUnit * sizeUnit, sizeUnit * sizeUnit);
                    unit.Location = new Point(x + temp.X, y + temp.Y);
                    unit.BackColor = Color.FromArgb(255, rnd.Next(255),
                        rnd.Next(255), rnd.Next(255));
                    unit.Click += Unit_Click;
                    plane.Controls.Add(unit);

                    temp.X += sizeUnit * 2;
                    temp.Y = 0;
                    numX++;

                } else {
                    continue;
               }
            }
        }
        numX = numX / numY; // determine number of boxes on X-axis
    }

    private static void Unit_Click(object sender, EventArgs e) {
        if (sender is PictureBox) {
            PictureBox p = (PictureBox)sender;
            MessageBox.Show(p.Location.ToString() + " = Number in x-axis " + numX + " - number in y-axis " + numY);
            return;
        }            
        throw new Exception("Not a picturebox for some reason. - " + sender.ToString());
    }        
}

}

Reap
  • 1,047
  • 13
  • 16
  • 3
    You should **avoid** statics when there is no reason for it. The whole idea of programming classes is to be able to reuse them. There is **NO** use for a background worker here, since you're only busy with controls. _Which cannot be accessed on a non-gui thread._ Don't generate ziljans of pictureboxes, use one instead. I recommend a reconsideration of the design. Some techniques have not been applied correctly. Lose the statics, lose the background worker. – Jeroen van Langen May 28 '18 at 08:56
  • I have reconsidered the entire design. The statics, background worker, and generating ~n^2 picturebox is no longer the case. It took me sometime to apply the techniques more eloquently, I needed time to reconsider the design. The first iteration I didn't bother looking into it too much, I was really concerned with results, however your constructive feedback enabled me to solve the problem a completely different way. – Reap Jun 03 '18 at 05:02

0 Answers0