-1

I am trying to use the save file dialog in a windows forms project of mine. When trying to save a file I use the showDialog() method and it throws a System.AccessViolationError. The initial directory of the save file dialog isn't set so I don't see why there is an access violation. Here's the code I wrote for using the save file dialog:

var imageSaver = new SaveFileDialog();
imageSaver.Filter = fileType + " File|*." + fileType;
imageSaver.Title = "Save Image";
if (imageSaver.ShowDialog() == DialogResult.OK)
{
    b.Save(imageSaver.FileName, imgFormat);
    Close();
}

This block of code is used in an event for when a button is clicked, however, after a bit of testing, I found out that the same code works when used in the constructor of the form and in the load event of the form.

Here is the entire class:

using System.Drawing.Imaging;

namespace Pixart
{
    public partial class ImageGenerator : Form
    {
        int width;
        int height;
        Cell[,] cells;
        ImageFormat imgFormat;
        string fileType;

        bool useMultiplier;

        public ImageGenerator(string fileType, ImageFormat imgFormat, Cell[,] cells, int width, int height)
        {
            InitializeComponent();
            this.width = width;
            this.height = height;
            this.cells = cells;
            this.imgFormat = imgFormat;
            this.fileType = fileType;

            titleLabel.Text = "Export " + fileType.ToUpper();

            widthNumber.Minimum = width;
            widthNumber.Increment = width;
            widthNumber.Maximum = (4000 / width) * width;
            heightNumber.Minimum = height;
            heightNumber.Increment = height;
            heightNumber.Maximum = (4000 / height) * height;

            if (heightNumber.Maximum / height < widthNumber.Maximum / width)
                multiplierNumber.Maximum = heightNumber.Maximum / height;
            else
                multiplierNumber.Maximum = widthNumber.Maximum / width;

            widthLabel.ForeColor = SystemColors.ControlDarkDark;
            heightLabel.ForeColor = SystemColors.ControlDarkDark;
            sizeLabel.ForeColor = SystemColors.ControlDarkDark;
            multiplierLabel.ForeColor = SystemColors.ControlText;
            useMultiplier = true;

            //The code works here for some reason
            //var imageSaver = new SaveFileDialog();
            //imageSaver.Filter = fileType + " File|*." + fileType;
            //imageSaver.Title = "Save Image";
            //if (imageSaver.ShowDialog() == DialogResult.OK)
            //{
                
            //}
        }

        private void ImageGenerator_Load(object sender, EventArgs e)
        {
            //The code also works here
            //var imageSaver = new SaveFileDialog();
            //imageSaver.Filter = fileType + " File|*." + fileType;
            //imageSaver.Title = "Save Image";
            //if (imageSaver.ShowDialog() == DialogResult.OK)
            //{

            //}
        }

        private void multiplierNumber_ValueChanged(object sender, EventArgs e)
        {
            widthLabel.ForeColor = SystemColors.ControlDarkDark;
            heightLabel.ForeColor = SystemColors.ControlDarkDark;
            sizeLabel.ForeColor = SystemColors.ControlDarkDark;
            multiplierLabel.ForeColor = SystemColors.ControlText;
            useMultiplier = true;
        }

        private void widthNumber_ValueChanged(object sender, EventArgs e)
        {
            widthLabel.ForeColor = SystemColors.ControlText;
            heightLabel.ForeColor = SystemColors.ControlText;
            multiplierLabel.ForeColor = SystemColors.ControlDarkDark;
            sizeLabel.ForeColor = SystemColors.ControlText;
            useMultiplier = false;

            widthNumber.Value = (widthNumber.Value / width) * width;
        }

        private void heightNumber_ValueChanged(object sender, EventArgs e)
        {
            widthLabel.ForeColor = SystemColors.ControlText;
            heightLabel.ForeColor = SystemColors.ControlText;
            multiplierLabel.ForeColor = SystemColors.ControlDarkDark;
            sizeLabel.ForeColor = SystemColors.ControlText;
            useMultiplier = false;

            heightNumber.Value = (Convert.ToInt32(heightNumber.Value) / height) * height;
        }

        private void saveButton_Click(object sender, EventArgs e)
        {
            int imageWidth = width * Convert.ToInt32(multiplierNumber.Value);
            int imageHeight = height * Convert.ToInt32(multiplierNumber.Value);
            if (!useMultiplier)
            {
                imageWidth = Convert.ToInt32(widthNumber.Value);
                imageHeight = Convert.ToInt32(heightNumber.Value);
            }

            using (Bitmap b = new Bitmap(imageWidth, imageHeight))
            {
                for (int r = 0; r < height; r++)
                {
                    for (int c = 0; c < width; c++)
                    {
                        for (int y = 0; y < imageHeight / height; y++)
                        {
                            for (int x = 0; x < imageWidth / width; x++)
                            {
                                b.SetPixel((c * (imageWidth / width)) + x, (r * (imageHeight / height)) + y, cells[c, r].Colour);
                            }
                        }
                    }
                }

                var imageSaver = new SaveFileDialog();
                imageSaver.Filter = fileType + " File|*." + fileType;
                imageSaver.Title = "Save Image";
                //line after this throws an error
                if (imageSaver.ShowDialog() == DialogResult.OK)
                {
                    b.Save(imageSaver.FileName, imgFormat);
                    Close();
                }
            }
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void ImageGenerator_Deactivate(object sender, EventArgs e)
        {
            Close();
        }
    }
}
Saffron
  • 3
  • 3
  • On exactly which line is the exception? Which version of .NET are you running? Are you using any unusual PInvoke or unsafe code? – Charlieface Jan 24 '22 at 18:03
  • Also, can you post the full exception message and stack trace? – John Glenn Jan 24 '22 at 18:08
  • The exception happens on the same line as "imageSaver.ShowDialog()". I am using .NET 4.7.2. I don't think I am using PInvoke or unsafe code but don't exactly know what either are. – Saffron Jan 24 '22 at 18:10
  • 1
    https://stackoverflow.com/questions/2560848/folderdialog-box-crashing-only-in-debug-mode-vsd2008/2562190#2562190 – Hans Passant Jan 24 '22 at 18:11
  • The exception message is System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.' I dont know how to get the stack trace sorry – Saffron Jan 24 '22 at 18:16
  • To get the stack trace, when Debugging (Debug => Start Debugging) and the exception shows. Click "Copy Details". Open "NotePad" and press ctrl-V to paste the stack trace into Notepad. – Tu deschizi eu inchid Jan 24 '22 at 18:27
  • Tried it, all it says is – Saffron Jan 24 '22 at 18:33
  • 1
    You'll need to post more code then. – Tu deschizi eu inchid Jan 24 '22 at 19:29

1 Answers1

1

The error message System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory in your code is occurring because the Form Deactivate event occurs when the SaveFileDialog opens.

The issue is due to the following code:

private void ImageGenerator_Deactivate(object sender, EventArgs e)
{
    Close();
}

Solution: Remove Close() (or comment it out)

private void ImageGenerator_Deactivate(object sender, EventArgs e)
{

}
Tu deschizi eu inchid
  • 4,117
  • 3
  • 13
  • 24