christian890
christian890

Reputation: 147

C# - Updating pictureBox.Image during Runtime causes Error

i am trying to change the pictureBox.Image during Runtime. I have several Model classes with a picture stored, whenever i click on a MenuStripItem i call the method "ChangePictureBoxImages". Till then there is no error (the pB is invisible!) but once i call the method to make the pB visible i get an Error. The Error code: "An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll".

Research said i should dispose the picturebox and set it to "null", however this does NOT help.

My Code:

using (Image current = BitmapManipulator.EvaluateMesurement(CSV_Name1, max_Rows, max_Col, var.TopImage, var.BitmapToManipulate, pB_ColourScale_Evaluation.Image, var.BitmapToManipulate, var.Filepath, var.FoldID))
                {

                    var.LastEvaluationImage = current;
                    BitmapManipulator.CombineImagesAndSaveThem_Evaluation(var.TopImage, var.BitmapToManipulate, pB_ColourScale_Evaluation.Image, var.Filepath, var.FoldID);  //saves the Files as jpg 
                    if (var.CurrentlyShownToUser) //checks if the MenuStripItem is the active one
                    {
                        if (var.LastEvaluationImage == null) { MessageBox.Show("the image is null");} //only for debugging purpose -> does never call
                        ChangePictureBoxImages(); 

                    }
                }

and the ChangePictureBoxImages():

      public void ChangePictureBoxImages()
    {

        foreach (Fold fold in FoldExisting)    
        {
            if (fold.FoldID == LastSelectedMenuStripItem_Name)       //the clicked item is the last Selected MenuStripItem
            {
                if (fold.LastEvaluationImage != null)
                {
                    Debug.WriteLine(pB_Evaluation_Bottom.Image.ToString() + "   " + fold.LastEvaluationImage.ToString());
                    pB_Evaluation_Bottom.Image = fold.LastEvaluationImage;
                }


                pB_Evaluation_Top.Image = fold.TopImage;
            }

        }
    }

There is no error till then, the error appears once i call "pB_Evaluation_Bottom.visible = true". (or if i called the visible method first first the error appears upon changing the Image!) The error also appears upon clicking 2 times on the MenuStripItem. I load the picture from the Class Fold as following:

This will set an image in the fold class, this image will then be manipulated and stored in LastEvaluationImage

        private void setTheImages(string PictureToManipulate, string PathToTopImage)
    {
        try
        {
            this.BitmapToManipulate_intern = (Image)Image.FromFile(@PictureToManipulate, true);
            this.TopImage_intern = (Image)Image.FromFile(@PathToTopImage, true);
        }
        catch (ArgumentNullException ex)
        {
            Debug.WriteLine("The BitMap for the manipulation process and the top image is not created.");
        }

    }

and the LastEvaluationImage where the last picture is stored -> this will be called to be the new pb.Image

        private Image LastEvaluationImage_intern;
    public Image LastEvaluationImage
    {
        get
        {
            return this.LastEvaluationImage_intern;
        }
        set
        {
            if (LastEvaluationImage_intern != null) { LastEvaluationImage_intern.Dispose(); LastEvaluationImage_intern = null; }
            this.LastEvaluationImage_intern = value;
            this.LastEvaluationTime_intern = DateTime.Now;
        }
    }

I know this is a little complex, but i hope someone can help me.

THANKS IN ADVANCE!

UPDATE: The Error must be in the following Code: The BitmapManipulator.EvaluateMeasurement Code :

 public Image EvaluateMesurement(double[][] MeasuredValues, int max_Rows, int max_Col, Image pB_Evaluation_Top, Image pB_Evaluation_Bottom, Image pB_EvaluationColourScale, Image ManipulatedBitmap, string PathMeasurementFiles, string Foldname) 
    {

        using (Bitmap bitmap = new Bitmap(ManipulatedBitmap))  
        {
            // the data array sizes:
            int number_nio = 0;
            int number_total = 0;
            List<FileInfo> LastFiles;   
            int got_number_for_trends = Properties.Settings.Default.TrendNumber;



            SolidBrush myBrush = new SolidBrush(red);

            using (Graphics g = Graphics.FromImage(bitmap))
            {
                Random rnd = new Random(8);
                int[,] data = new int[max_Col, max_Rows];



                // scale the tile size:
                float sx = 1f * bitmap.Width / data.GetLength(0);
                float sy = 1f * bitmap.Height / data.GetLength(1);

                LastFiles = FM.GetLastFiles_Trend(ref got_number_for_trends, PathMeasurementFiles);  
                double[][] CSV_Statistiken = FM.LastFilesToCSV(got_number_for_trends, true, LastFiles, PathMeasurementFiles);    


                for (int x = 0; x < max_Col; x++)     
                {
                    for (int y = max_Rows - 1; y >= 0; y--)  
                    {
                        number_total++;
                        RectangleF r = new RectangleF(x * sx, y * sy, sx, sy);

                        if (MeasuredValues[y][x] < Properties.Settings.Default.Threshhold) 
                        {
                            number_nio++;
                            if (CSV_Statistiken[y][x] == Properties.Settings.Default.TrendNumber)  
                            {
                                myBrush.Color = Color.FromArgb(150, black);
                                g.FillRectangle(myBrush, r);
                            }
                            else
                            {
                                myBrush.Color = Color.FromArgb(150, red);
                                g.FillRectangle(myBrush, r);
                            }

                        }
                        else    
                        {

                            myBrush.Color = Color.FromArgb(150, green);
                            g.FillRectangle(myBrush, r);
                        }

                    }


                }
            }

            return bitmap;  
        }
    }

This returned bitmap will be stored in fold.LastEvaluationImage as following:

using (Image current = BitmapManipulator.EvaluateMesurement(CSV_Name1, max_Rows, max_Col, var.TopImage, var.BitmapToManipulate, pB_ColourScale_Evaluation.Image, var.BitmapToManipulate, var.Filepath, var.FoldID))
            {

                var.LastEvaluationImage = current;
            }

Upvotes: 2

Views: 935

Answers (1)

Luaan
Luaan

Reputation: 63732

You're returning a disposed bitmap. It shouldn't be surprising you can't draw something that no longer exists :)

The using (bitmap) is the last thing you want in this case. The bitmap must survive longer than the scope of the using. And the using (current) in the caller has the same problem - you're again disposing the image way too early. You can only dispose it when it's clear that it isn't going to be used ever again - e.g. when you replace it with a new image.

To elaborate, using does nothing but call Dispose when you leave its scope. In the case of Bitmap (which is just a "thin" wrapper around a GDI bitmap), this releases the memory where the actual image data is stored. There isn't anything interesting left, so there's nothing to draw (and you'd basically be calling DrawBitmap(NULL) as far as GDI is concerned).

Upvotes: 1

Related Questions