C# 在C中处理OpenFileDialog?

C# 在C中处理OpenFileDialog?,c#,picturebox,dispose,using,openfiledialog,C#,Picturebox,Dispose,Using,Openfiledialog,我搜索了整个StackOverflow,但找不到以下问题的答案: 当我使用时,我打开的文件会被阻止在我的程序之外使用,直到我关闭我的程序。因此,如果我打开一个图像,我就不允许在我的文件中替换该图像 我想这是处理我的OpenFileDialog的一个问题,但我不知道如何解决它 我的代码: using (OpenFileDialog ofd = new OpenFileDialog()) { ofd.Title = "Open Image"; ofd.Filter = "PNG Im

我搜索了整个StackOverflow,但找不到以下问题的答案:

当我使用时,我打开的文件会被阻止在我的程序之外使用,直到我关闭我的程序。因此,如果我打开一个图像,我就不允许在我的文件中替换该图像

我想这是处理我的OpenFileDialog的一个问题,但我不知道如何解决它

我的代码:

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);
    }
}

我认为使用块可以解决这个问题,但是没有。。。它仍然被程序使用。我希望将图像加载到picturebox中,然后我希望图像再次可用,以便我可以重命名、替换它等等……

这与OpenFileDialog无关。不可能,因为对话框实际上没有打开文件。它只允许用户选择要打开的文件,然后将该路径返回给您,以便您可以编写代码来打开该文件。此外,通过使用using语句,您正确地处理了OpenFileDialog

这里的问题来自于您实际将文件-ofd.FileName-作为位图打开。使用时,磁盘上包含图像的文件将保持锁定状态,直到位图对象被释放。文件如是说:

在释放位图之前,文件将保持锁定状态

因为您正在将位图分配给pictureBox1.Image,所以在释放pictureBox1之前不会释放位图对象。因此,磁盘上的映像文件将保持锁定状态

如果要解锁该文件,则需要制作位图的副本并处理原始图像,或者在使用完PictureBox后清除PictureBox并处理其以前的图像

据我所知,您的问题听起来像是希望能够对磁盘上的图像文件进行更改,同时继续在图片框中显示图像。如果是这样的话,你需要复印一份。使用获取图像的构造函数重载执行此操作,如下所示:

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;
    }
}

正如Chris所写,尝试以下内容:

pictureBox1.Image = Image.FromStream(new MemoryStream(File.ReadAllBytes(old.FileName)));
它使用file.ReadAllBytes读取所有文件,将其放入MemoryStream并将MemoryStream传递给图像静态初始值设定项

相当于:

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

你不能处理内存流!如果/当图像将被释放时,如果您没有对ms的其他引用,MemoryStream的终结器将启动,并且MemoryStream将被释放请注意,这不会立即发生。。。GC运行时会发生这种情况。我发现最好的技术是使用file.ReadAllBytes打开和关闭文件,将文件读入字节数组,然后使用ImageConverter将字节数组转换为图像。例如,请参见此处:

编辑:
引用我上一篇文章的话:我尝试过的其他一些技术不是最佳的,因为它们改变了24位与32位像素的位深度,或者忽略了图像的分辨率dpi。

我可以确认这可能就是问题所在。我曾经被它咬过。一个选项可以考虑在文件字节中读取,而不是从内存流中创建位图。@克里斯,你确定流不会锁定文件吗?请记住,您必须在创建位图对象的整个生命周期内保持流的打开状态。您获得了所有投票,您确实需要修复您的答案。克隆创建一个浅拷贝,它仍然使用原始位图的像素数据。因此不会释放文件上的锁。请随意使用我的答案,我会删除我的。@Hans Oops,谢谢。我不记得克隆人创建了位图的深度副本。修复…您的代码不可复制不是问题所在。我先尝试了一下,制作了一个克隆,处理了旧拷贝,然后使用了克隆。但是我最终得到了同样的错误,所以我回到这里,检查了第二个答案,那就是xanatos的答案。非常感谢你已经付出了努力,我想我在实现你的意思时做错了什么!。真的非常感谢!非常感谢你。我从字面上复制了你的代码规则,它立即生效,非常感谢!!哎呀,我猜这就是我的答案:没有可复制的可复制代码。哦,好吧,经常发生在我身上。我仍然认为克隆位图比泄漏内存流更好。这将永远无法通过代码审查,需要大量注释;就像你提到的,这很不直观。@CodyGray我给了你一个+1,但重点是Chris在使用MemoryStream类的评论中给出了最后一英里。你的回答非常理论化。对,重点是我不同意这个解决方案是最优的。如果我认为这是一个好主意,我会在我的回答中写下它。我只想提到,如果我没记错的话,所有不使用ImageConverter的技术都有一个小问题,因为否则位深度总是设置为32位,而d pi设置为屏幕的dpi。这通常并不重要,但如果您想保留源图像的位深度和dpi,则不太好。但我不是100%确定。。。