簡體   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