关于C#中PictureBox加载动态GIF所出现的BUG以及解决方法

近日项目,需要用到动态的GIF做背景。于是从PictureBox继承了一个控件,希望以最少的代码解决动态背景的问题。
 
     起先一切都顺利,用PictureBox的Image属性很快就能够搞定一切,能够支持的图片格式也基本满足要求,遂以为一切大功告成。工作完成,我需要将背景图片等信息保存,然后在另外一个程序中打开、运行(一个设计时效果,一个运行时效果)。然而,再次打开时,程序报错:GDI+中出现一般性错误(Generic error in GDI+),报错的代码是base.Paint(e),也就是执行PictureBox基类的Paint函数时出错。
 
    保存图片的代码是这样的:
              MemoryStream ms = new MemoryStream();
              this.Image.Save(ms, Image.RawFormat);
 
              byte[] serializedObject = ms.ToArray();
              ms.Close();
              XmlElement value = node.OwnerDocument.CreateElement("Image");
              String strImage = Convert.ToBase64String(serializedObject);
              value.AppendChild(node.OwnerDocument.CreateTextNode(strImage));
              bkImage.AppendChild(value);
 
  打开是其逆过程:
            XmlElement value = xmlImage.SelectSingleNode("Image") as XmlElement;
            if (value == null)
                return;
            byte[] dsBytes;
            dsBytes = Convert.FromBase64String(value.InnerText);
            if (dsBytes.Length > 0)
            {
                MemoryStream ms = new MemoryStream(dsBytes);
                this.Image = Image.FromStream(ms);
 
                ms.Close();
            }
 
  自认为这样的代码不会有错的,除非反持续化过程中图片的格式发生了改变。可是跟踪下去,发现持续化前后图片类型的GUID是相同的,由此肯定图片格式没有出错。
 
    那问题在哪里?
 
    VS2005的异常报告里面显示,是在Image.SelectActiveFrame()这个函数里面出错了,查MSDN,没有任何有用的信息。于是Google,一搜才知道,原来不少人都遇到了这个问题。于是兴奋,以为会有很好的解决方法。可惜失望了,遇到这个问题的人不少,可有解决方法的却寥寥无几。似乎我找到的唯一的一个解决办法就是使用Load()函数代替动态创建图片,这显然不能满足我的需求(我需要将图片也保存到XML字段中)。
 
   无奈,只能自己想办法。
 
  找不到问题的原因(不能跟踪,系统代码),就只能猜测。我的思路是:我仅仅保存了Image属性的图片,也许,Image属性还有其它分量。那么,我应当保存整个Image属性,而不仅仅是其引用的图片。
 
于是修改代码,保存属性的代码如下:
            if (this.Image != null)
            {
                bkImage.SetAttribute("IsSet", "1");
                PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(this);
                PropertyDescriptor ptyImage = properties.Find("Image", false);
                if (ptyImage != null)
                {
                    MemoryStream ms = new MemoryStream();
                    BinaryFormatter format = new BinaryFormatter();
                    object obj = ptyImage.GetValue(this);
                    format.Serialize(ms, obj);
                    ms.Seek(0, 0);
                    byte[] serializedObject = ms.ToArray();
                    ms.Close();
                    XmlElement value = node.OwnerDocument.CreateElement("Image");
                    String strImage = Convert.ToBase64String(serializedObject);
                    value.AppendChild(node.OwnerDocument.CreateTextNode(strImage));
                    bkImage.AppendChild(value);
                }
            }
            else
                bkImage.SetAttribute("IsSet", "0");
 
恢复属性的代码:
             byte[] dsBytes;
            dsBytes = Convert.FromBase64String(value.InnerText);
            if (dsBytes.Length > 0)
            {
                MemoryStream ms = new MemoryStream(dsBytes);
                BinaryFormatter format = new BinaryFormatter();
                object obj = format.Deserialize(ms);
                PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(this);
                PropertyDescriptor ptyImage = properties.Find("Image", false);
                if (ptyImage != null)
                    ptyImage.SetValue(this, obj);
                ms.Close();
            }
 
编译,通过;运行,保存成功;关闭,再次打开,GIF在动,激动啊!
 
总结:我把整个属性以二进制的形式保存下来,这些内容相当于是从内存里面抠出来的,等到需要的时候再次写回内存,类似于XP里面的休眠机制,能够避免一些系统底层的未知原因导致的错误。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: C#PictureBox控件的属性包括: 1. Image:设置或获取PictureBox控件显示的图像。 2. SizeMode:设置或获取PictureBox控件图像的显示方式。 3. BorderStyle:设置或获取PictureBox控件的边框样式。 4. BackColor:设置或获取PictureBox控件的背景颜色。 5. Enabled:设置或获取PictureBox控件是否启用。 6. Visible:设置或获取PictureBox控件是否可见。 7. Location:设置或获取PictureBox控件在父容器的位置。 8. Cursor:设置或获取PictureBox控件的光标。 9. ContextMenuStrip:设置或获取PictureBox控件的快捷菜单。 10. Dock:设置或获取PictureBox控件在父容器的停靠方式。 11. Padding:设置或获取PictureBox控件的内边距。 12. TabIndex:设置或获取PictureBox控件在Tab键顺序的索引。 13. TabStop:设置或获取PictureBox控件是否可以通过Tab键获得焦点。 14. Text:设置或获取PictureBox控件的文本。 15. Tag:设置或获取PictureBox控件的标记。 ### 回答2: 首先,C 是一种计算机编程语言。它由贝尔实验室的丹尼斯·里奇和肯·汤普逊在20世纪70年代初期开发出来。 C 是一种强类型的语言,它具有高效和灵活的特点,表达简洁富有表现力。它被广泛应用于操作系统的开发和一些系统软件的编写,如编译器、文本编辑器、数据库管理系统等。它还被用于开发游戏、桌面应用程序、科学计算等方面。 C 语言的语法十分严谨,要求开发者严谨的进行程序设计,这种严谨使开发人员在编写代码时能够克服更多错误,提高程序质量。它的语法近似于自然语言,易于阅读,而且学习使用 C 为后续学习其他计算机语言打下坚实的基础。 C 语言被广泛使用,并且仍然是大多数编程语言的基础。很多其他的计算机语言都借鉴了 C 语言的语法设计,如 C++、Java、Python等。因其灵活性、强大性以及广泛性,C 语言在当前计算机科学领域仍然是一门非常重要的编程语言。 ### 回答3: 我很抱歉,您没有提供任何问题或话题,因此无法为您提供相关回答。如果您能够提供更多信息,我会非常乐意根据您提供的信息为您提供详细的文回答。谢谢。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值