質問

I have searched throughout entire Stack Overflow, but I couldn't find an answer to the following:

When I'm using my OpenFileDialog, the files I open get blocked for use out of my program until I close my program. So if I open an image, I am not allowed to replace that image in my Windows Explorer anymore.

I think this is a problem with disposing my OpenFileDialog, but I'm not sure how to solve it...

My code:

using (OpenFileDialog ofd = new OpenFileDialog())
{
    ofd.Title = "Open Image";
    ofd.Filter = "PNG Image(*.png|*.png" +
                 "|GIF Image(*.gif|*.gif" +
                 "|Bitmap Image(*.bmp|*.bmp" +
                 "|JPEG Compressed Image (*.jpg|*.jpg";

    if (ofd.ShowDialog() == DialogResult.OK)
    {
        pictureBox1.Image = new Bitmap(ofd.FileName);
    }
}

I thought that the using block would solve this problem, but nope... It still gets used by the program. I want to load the image in the picturebox and then I want the image to be available again (so I can rename it, replace it, etc...).

役に立ちましたか?

解決 2

As written by Chris, try something like:

pictureBox1.Image = Image.FromStream(new MemoryStream(File.ReadAllBytes(old.FileName)));

It reads all the file with File.ReadAllBytes, put it in a MemoryStream and pass the MemoryStream to the Image static initializer.

Equivalent to:

byte[] bytes = File.ReadAllBytes(old.FileName);
MemoryStream ms = new MemoryStream(bytes);
pictureBox1.Image = Image.FromStream(ms);

You mustn't dispose the MemoryStream! If/when the Image will be disposed, the finalizer of MemoryStream will kick in (if you don't have other references to ms) and the MemoryStream will be disposed (note that this isn't something that will happen immediately... It's something that will happen when the GC will run)

他のヒント

This is not related to the OpenFileDialog. It couldn't possibly be, because the dialog doesn't actually open the file. It just allows the user to select a file to open, and then returns that path to you so that you can write code that opens the file. Besides, you're correctly disposing of the OpenFileDialog through your use of the using statement.

The problem here comes from your actually opening the file—ofd.FileName—as a Bitmap. When you use the Bitmap constructor overload that accepts a path string, the file on disk that contains the image remains locked until the Bitmap object is disposed. So says the documentation:

The file remains locked until the Bitmap is disposed.

Because you're assigning the bitmap to pictureBox1.Image, the Bitmap object will not be disposed until pictureBox1 is disposed. And therefore your image file on disk will remain locked.

If you want to unlock the file, you will either need to make a copy of the bitmap and dispose the original, or clear out the PictureBox and dispose its previous image when you are finished with it.

As I understand your question, it sounds like you want to be able to make changes to the image file on disk while continuing to display the image in the picture box. If that's the case, you will need to make a copy. Do that using the constructor overload that takes an Image, like this:

if (ofd.ShowDialog() == DialogResult.OK)
{
    // Load the image the user selected
    using (Image img = Image.FromFile(ofd.FileName))
    {
        // Create a copy of it
        Bitmap bmpCopy = new Bitmap(img);

        // Clear out the bitmap currently in the picture box,
        // if there is one.
        if (pictureBox1.Image != null)
        {
            pictureBox1.Image.Dispose();
        }

        // Assign the copy of the bitmap to the picture box.
        pictureBox1.Image = bmpCopy;
    }
}

The technique I've found to be best is to read the file into a byte array with File.ReadAllBytes() (that opens and closes the file), and then use ImageConverter to convert the byte array into an Image. See here for example: https://stackoverflow.com/a/16576471/253938

Edit: Quote from that previous post of mine: "Some of the other techniques I've tried have been non-optimal because they changed the bit depth of the pixels (24-bit vs. 32-bit) or ignored the image's resolution (dpi)."

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top