繁体   English   中英

在Winforms中显示动画gif而不锁定文件

[英]Showing animated gif in Winforms without locking the file

我正在尝试在Winforms应用程序中显示各种文件类型的图像(包括动画.gif文件)。 我还必须能够修改显示的文件 (更改文件名,删除它们)。

问题是Picturebox锁定图像文件,直到应用程序关闭时使用正常方式。

这意味着我不能这样做:

private void Form1_Load(object sender, EventArgs e)
    {

        PictureBox pic = new PictureBox();
        pic.Size = new Size(250, 250);
        pic.Image = Image.FromFile("someImage.gif");
        this.Controls.Add(pic);

                    //No use to call pic.Image = null or .Dispose of it
        File.Delete("someImage.gif"); //throws exception
    }

上面链接中的解决方法如下:

    private void Form1_Load2(object sender, EventArgs e)
    {
        PictureBox pic = new PictureBox();
        pic.Size = new Size(250, 250);
                    //using a FileStream
        var fs = new System.IO.FileStream("someImage.gif", System.IO.FileMode.Open, System.IO.FileAccess.Read);
        pic.Image = System.Drawing.Image.FromStream(fs);
        fs.Close();

        this.Controls.Add(pic);

        pic.MouseClick += pic_MouseClick;
    }

这适用于普通图像类型,但它不会加载动画.gifs,这对我很重要。 尝试加载一个将使它看起来像这样

我已经找到了一些关于它的主题( 这个这个 ),但它们都是关于WPF并使用BitmapImage。 我已经搜索了如何在Winforms应用程序中使用BitmapImage,但除了应该以某种方式工作之外没有找到任何东西。

我想留在Winforms,因为我只是习惯了它,但这不是必需品。

总结一下:我需要一种方法来显示常见的图像类型(png,jpg,bmp和动画gif),同时仍然能够修改HDD上的文件。 如果这意味着卸载 - >修改 - >重新加载文件,那就没关系。 我更喜欢Winforms,但其他框架也可以。

谢谢你的帮助。

编辑:我尝试过的另一种方式

using (System.IO.FileStream fs = new System.IO.FileStream("E:\\Pics\\small.gif", System.IO.FileMode.Open, System.IO.FileAccess.Read))
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            fs.CopyTo(ms);
            pic.Image = Image.FromStream(ms);
        } 

但显示与第二个例子相同的问题。 gif没有加载。

使用MemoryStream确实是避免文件锁定的正确方法。 这是一个强大的优化btw,锁是由内存映射文件创建的,Image类用它来保持像素数据不在页面文件中。 当位图很大时,这很重要。 希望不是动画的GIF :)

您的代码段中的一个小错误,您忘记将流重置回数据的开头。 固定:

 using (var fs = new System.IO.FileStream(...)) {
     var ms = new System.IO.MemoryStream();
     fs.CopyTo(ms);
     ms.Position = 0;                               // <=== here
     if (pic.Image != null) pic.Image.Dispose(); 
     pic.Image = Image.FromStream(ms);
 } 

在情况下,它需要说:请不要将其内存流。 这导致很难诊断随后的随机崩溃,像素数据被懒惰地读取。

实际上,您必须在内存中制作图像文件的副本

.Net 4.0 (2.0,3.0,3.5)之前,你必须创建一个FileStream并将其复制到MemoryStream并回放它,如另一个答案所示。

由于.Net 4.0 (4.0,4.5,...)Image.FromFile支持动画GIF


如果您使用.Net 4.0更高版本,则以下方法就足够了:

使用System.IOSystem.DrawingSystem.Drawing.Imaging

 private void Form1_Load(object sender, EventArgs e)
    {
        string szTarget = "C:\\someImage.gif";

        PictureBox pic = new PictureBox();
        pic.Dock = DockStyle.Fill;

        Image img = Image.FromFile(szTarget);   // Load image fromFile into Image object

        MemoryStream mstr = new MemoryStream(); // Create a new MemoryStream
        img.Save(mstr, ImageFormat.Gif);        // Save Image to MemoryStream from Image object

        pic.Image = Image.FromStream(mstr); // Load Image from MemoryStream into PictureBox
        this.Controls.Add(pic); 

        img.Dispose(); // Dispose original Image object (fromFile)
        // after this you should be able to delete/manipulate the file

        File.Delete(szTarget);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM