【IT168 技术文档】
自从gif动画格式推出这十几年来,可是忙坏了C/C++的程序员。远的不说,就说这几年吧,各种方法可谓五花八门,有的直读文件,一行一行不厌其烦的分析;有的使用IPicture,大把大把的玩接口;有的封装成COM,谁也不知道他怎么实现的。现在有了GDI+,大家更忙活了,所以我写了这篇文章。
其实只要使用.Net框架封装好的几个函数,就能轻松搞定了。
第一步:新建一个.Net窗体工程。
(新建.Net窗体工程)
第二步:添加成员变量和消息,只要双击空白处系统就会自动填写默认函数,添加图中的三个函数就够了。

(添加成员变量和消息)
第三步:添加成员变量image及在Form1_Load中初始化。
private:Image *image;
private: System::Void Form1_Load(System::Object * sender, System::EventArgs * e)
{
//按路径读入文件
image=Image::FromFile(L"测试图片.GIF");
}
private: System::Void Form1_Closed(System::Object * sender, System::EventArgs * e)
{
if(image) image->Dispose();
}
第四步:好了,动画文件已经读入,现在的任务是把它显示出来。
private: System::Void Form1_Paint(System::Object * sender,
System::Windows::Forms::PaintEventArgs * e)
{
//在Form1_Paint中启用动画,这个函数的功能是读取图片中每个对象的时间信息
//然后每到一次时间就调用一次OnPaintGIF
ImageAnimator::Animate(image, new EventHandler(this,OnPaintGIF));
//显示图片
e->Graphics->DrawImage(0,0,image->Width,image->Height);
//将图片按照时间间隔向后翻一页
ImageAnimator::UpdateFrames(image);
}
private: System::Void OnPaintGIF(Object* sender, EventArgs* e)
{
//时间到啦,该显示下一张图啦,置显示区域无效
this->Invalidate();
到此,已经可以正确显示GIF格式的动画了,简单吧,才几行就解决了。
不过大家仔细观察会发现,图片一闪一闪的,很不好看.....那怎么办呢?用双缓冲方法?非也,根本就不是一码事!图片闪铄的问题几乎每天都能在论坛上看到,我在这里顺便说一下原因。数据量大时的闪动是因为计算机来不及载入数据,这时可以用双缓冲法;但是数据量不大时图片闪动是因为当程序置屏幕无效时框架会用背景色来擦除,这样就会闪一下,这时用双缓冲法就无效了。后者在MFC中我们可以响应OnEraseBkgnd()来解决;可是在.net中找不到这个消息,怎么办呢?其实只要避开屏幕无效就好了,请往下看:
private:
Image *image;
Graphics *p;//添加一个用来显示的变量
private: System::Void Form1_Load(System::Object * sender,
System::EventArgs * e)
{
image=Image::FromFile(L"测试图片.GIF");
//按路径读入文件
p=Graphics::FromHwnd(this->Handle);
//按窗口句柄创建Graphics
ImageAnimator::Animate(image, new EventHandler(this,OnPaintGIF));
//启动动画
}
private: System::Void Form1_Closed(System::Object * sender,
System::EventArgs * e)
{
if(p) p->Dispose();
if(image) image->Dispose();
}
private: System::Void OnPaintGIF(Object* o, EventArgs* e)
{
p->DrawImage(image,0,0,image->Width,image->Height);
//显示图片
ImageAnimator::UpdateFrames();
}
private: System::Void Form1_Paint(System::Object * sender,
System::Windows::Forms::PaintEventArgs * e)
{
//这个可以不要,在属性页中删除所有文字即可自动删除代码
}
这样就把图像的闪烁问题也解决了。
总结
由于使用.net封装类,所以只要Animate()启动动画,然后UpdateFrames()翻页即可,十分简便;由于上面那两个函数的具体功能和使用方法(特别是UpdateFrames()的参数)找不到详细描述的文档;按窗口句柄创建Graphics那句,开始想this->GetSafeHwnd();后来xxx.m_hWnd;最后终于发现了this->Handle。