创建基于 Microsoft .NET Compact Framework 的动画控件






3.67/5 (12投票s)
了解如何构建一个基于 .NET Compact Framework 的动画控件。
本文由 MSDN 提供。
目录
引言
在最近的一个项目中,其中一个要求是在 Microsoft® .NET Compact Framework Windows® 窗体上显示一个动画 GIF。 .NET Compact Framework 的 1.0 版本不具备显示动画 GIF 文件的能力,也不包含完整 .NET Framework 中的 `ImageAnimator` 辅助类。 `ImageAnimator` 类允许动画化具有基于时间的帧的图像。
尽管可以编写 C# 代码来读取 GIF86a 格式的动画 GIF,但我选择了一种更简单、更直接的方式在我的程序中显示动画。
创建故事板
如果您使用您选择的 GIF 编辑器打开一个动画 GIF,您会看到该文件包含几个连续的图像(**帧**)
图 1. 动画帧
这些图像以压缩格式存储,包含有关尺寸、数量和帧之间延迟时间的信息。显示动画的程序会读取这些信息。
许多 GIF 编辑器允许您将图像帧提取为帧的顺序“故事板”
图 2. 故事板
我将其保存到一个单独的位图文件中,后来将其转换为 GIF 格式,因为它在 .NET Compact Framework 中占用的内存更少。现在我将向您展示如何使用此图像创建基于 .NET Compact Framework 的动画控件。
开始动画
我们将要动画化位图的方式相当简单。它依赖于这样一个事实:当您在 .NET Compact Framework 中使用图像时,您不必显示加载到内存中的整个图像。 `graphics.DrawImage` 方法的一个重载版本接受 `Rectangle` 对象作为参数。这个矩形将是我们的方式,用于框定故事板位图中的每个图像。通过移动帧矩形的位置,我们可以动态地加载位图的不同部分显示在我们的窗体上。
我们在 .NET Compact Framework 项目中添加一个名为 `AnimateCtl` 的新类,并将此类派生自 `System.Windows.Forms.Control`
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
public class AnimateCtl : System.Windows.Forms.Control
{
// Add class implementation here
}
让我们向该类添加一个 `public` `Bitmap` 属性,用于从客户端传递位图。不要忘记声明一个 `private` 位图成员,供类内部使用
private Bitmap bitmap;
public Bitmap Bitmap
{
get
{
return bitmap;
}
set
{
bitmap = value;
{
{
我们创建的控件将使用从控件检索到的 `Graphics` 对象的 `DrawImage` 方法来绘制帧
private void Draw(int iframe)
{
//Calculate the left location of the drawing frame
int XLocation = iframe * frameWidth;
Rectangle rect = new Rectangle(XLocation, 0, frameWidth, frameHeight);
//Draw image
graphics.DrawImage(bitmap, 0, 0, rect, GraphicsUnit.Pixel);
}
此方法接受需要绘制的当前帧号。然后,我们通过计算其左侧位置来创建绘图矩形。
为了实现控件的循环逻辑,我选择了使用 `System.Windows.Forms.Timer`。
尽管还有许多其他选项可以提供相同的功能,例如 `System.Threading.Timer` 甚至创建单独的线程,但 `System.Windows.Forms.Timer` 的使用被证明是一种更简单、更便捷的方法。让我们在控件的构造函数中添加以下代码
public AnimateCtl()
{
//Cache the Graphics object
graphics = this.CreateGraphics();
//Instantiate the Timer
fTimer = new System.Windows.Forms.Timer();
//Hook up to the Timer's Tick event
fTimer.Tick += new System.EventHandler(this.timer1_Tick);
}
在构造函数中,我们缓存控件实例的 `Graphics` 对象并创建一个新的 `Timer` 实例。并且我们不应忘记将 `Timer` 的 `Tick` 事件挂接起来。我们已准备好插入 `StartAnimation` 方法,该方法将实际启动动画
public void StartAnimation(int frWidth, int DelayInterval, int LoopCount)
{
frameWidth = frWidth;
//How many times to loop
loopCount = LoopCount;
//Reset loop counter
loopCounter = 0;
//Calculate the frameCount
frameCount = bitmap.Width / frameWidth;
frameHeight = bitmap.Height;
//Resize the control
this.Size(frameWidth, frameHeight);
//Assign delay interval to the timer
fTimer.Interval = DelayInterval;
//Start the timer
fTimer.Enabled = true;
}
此方法接受一些对动画非常重要的参数:帧宽度、延迟间隔和循环次数。
别忘了循环逻辑
private void timer1_Tick(object sender, System.EventArgs e)
{
if (loopCount == -1) //loop continuously
{
this.DrawFrame();
}
else
{
if (loopCount == loopCounter) //stop the animation
fTimer.Enabled = false;
else
this.DrawFrame();
}
}
private void DrawFrame()
{
if (currentFrame < frameCount-1)
{
//move to the next frame
currentFrame++;
}
else
{
//increment the loopCounter
loopCounter++;
currentFrame = 0;
}
Draw(currentFrame);
}
在上面的代码中,在 `timer1_Tick` 事件中,我们检查 `loopCount`(它跟踪已经绘制了多少次循环),并将其与调用 `StartAnimation` 方法时捕获的 `loopCounter` 进行比较。
电影时间!
我们已经完成了 `AnimateCtl`,可以开始实际测试了。首先,我们需要将带有“故事板”的图像文件添加到您的项目中。我们可以通过将此文件设为嵌入资源,或者只需告诉 Visual Studio .NET 2003 将此文件作为项目的一部分进行复制。在解决方案资源管理器中右键单击项目,然后从弹出菜单中选择“添加现有项…”浏览到图像文件,并确保该文件的 `Build Action` 属性设置为 `Content`。
现在,让我们将以下内容插入到您的 `Form` 的构造函数中
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//Instantiate control
animCtl = new AnimateCtl();
//Assign the Bitmap from the image file
animCtl.Bitmap = new Bitmap(@"\Program Files\AnimateControl\guestbk.gif");
//Set the location
animCtl.Location = new Point(50, 50);
//Add to control to the Form
this.Controls.Add(animCtl);
}
在上面的代码中,我们将动画控件的 `Bitmap` 属性分配给从我们的图像文件创建的 `Bitmap` 对象。
在设计器中将两个按钮放在您的窗体上,并为它们的点击事件添加代码
private void button1_Click(object sender, System.EventArgs e)
{
animCtl.StartAnimation(92, 100, 3);
}
private void button2_Click(object sender, System.EventArgs e)
{
animCtl.StopAnimation();
}
运行项目并点击“开始动画”按钮时,您应该会看到动画
图 3. 最终产品
伪动画 GIF 文件中包含的帧数以及帧之间的延迟时间可能会有所不同。在调用 `StartAnimation` 方法时,您肯定需要根据不同的动画调整 `DelayInterval` 参数。
此代码绝非最终版本。 `AnimateCtl` 没有提供可以集成到动画 GIF 中的所有必需功能。例如,`AnimateCtl` 控件无法处理帧之间不同的延迟时间。例如,您可能希望第一个帧显示的时间比其他帧稍长一些。本文提供的代码是您扩展此控件以满足您需求的良好起点。
请记住,显示高分辨率图形动画可能会给系统资源带来很大负担。请注意您可能在其上运行此代码的某些设备的内存和资源限制。不要忘记彻底测试它,并确保您的应用程序没有占用所有内存或占用所有处理器时间。
结论
尽管 .NET Compact Framework 是完整 .NET Framework 的一个子集,但开发人员仍然有能力创建引人注目的用户界面,从而吸引最终用户。通过利用可用的 GIF 编辑器工具和 .NET Compact Framework 的绘图功能,我们能够在他们的智能设备项目中显示动画。