建立基于 Microsoft .NET Framework 精簡版的動畫控件
引自:http://www.microsoft.com/china/msdn/archives/library/dnnetcomp/html/animationcontrol.asp
Alex Yakhnin
IntelliProg, Inc.
2003年3月
适用于:
Microsoft® .NET Framework 精簡版
Microsoft Visual Studio® .NET 2003
Microsoft Windows® CE .NET
摘要:學習如何建立基于 .NET Framework 精簡版的動畫控件。
下載下傳 AnimationControl.msi(英文)。(請注意,在示例檔案中,程式員的注釋使用的是英文,本文中将其譯為中文是為了便于讀者了解。)
目錄
- 簡介
- 建立情節
- 讓我們動起來
- 演出開始!
- 小結
簡介
在最近的項目中,有一項要求是在 Microsoft® .NET Framework 精簡版的 Windows® 窗體中顯示動畫 GIF。.NET Framework 精簡版的 1.0 版沒有顯示動畫 GIF 檔案的功能,也不包含 .NET Framework 完整版中的
ImageAnimator輔助類。通過
ImageAnimator類可以為基于時間幀的圖像制作動畫。
盡管可以編寫 C# 代碼讀取 GIF86a 格式的動畫 GIF,但是我在程式中選擇了一種更簡單直覺的方法來顯示動畫。
建立情節
如果您在標明的 GIF 編輯器中打開一個動畫 GIF,将會看到此檔案是由互相銜接的多個圖像(幀)組成的:
圖 1:動畫幀這些圖像以壓縮格式存儲,并附帶有關大小、數量和幀之間的延遲時間的資訊。這些資訊由顯示動畫的程式讀取。
許多 GIF 編輯器允許您将圖像幀提取到順序排列的“故事闆”中:
圖 2:故事闆我将故事闆儲存在一個位圖檔案中,後來将此檔案轉換為 GIF 格式,因為此格式的檔案在 .NET Framework 精簡版中占用的記憶體較少。現在我要向您示範如何使用此圖像建立基于 .NET Framework 精簡版的“動畫”控件。
讓我們動起來
我們所使用的讓此位圖動起來的方法相當簡單。它基于這樣一個事實,當您在 .NET Framework 精簡版中使用圖像時,不必顯示載入記憶體的整個圖像。
graphics.DrawImage方法的一個重載方法将 Rectangle 對象作為參數接受。我們就用這個矩形将故事闆位圖中的每個圖像作為幀來處理。通過移動幀矩形的位置,我們可以動态載入要在窗體中顯示的位圖的不同部分。
我們向 .NET 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
{
// 在此添加類的實作
}
向這個類中添加一個公共的 Bitmap 屬性,用于從用戶端傳遞位圖。不要忘記為這個位圖聲明一個私有成員,以便在類中使用:
private Bitmap bitmap;
public Bitmap Bitmap
{
get
{
return bitmap;
}
set
{
bitmap = value;
{
{
我們建立的這個控件将使用在其中檢索的
Graphics對象的
DrawImage方法來繪制這些幀:
private void Draw(int iframe)
{
//計算圖形框的左邊位置
int XLocation = iframe * frameWidth;
Rectangle rect = new Rectangle(XLocation, 0, frameWidth,
frameHeight);
//繪制圖像
graphics.DrawImage(bitmap, 0, 0, rect, GraphicsUnit.Pixel);
}
此方法接受需要繪制的目前幀号。然後計算圖形框的左邊位置以建立矩形。
為了實作該控件的循環邏輯,我選擇使用
System.Windows.Forms.Timer。
還有不少其他選項可以提供同樣的功能,例如使用
System.Threading.Timer或是建立一個單獨的線程也可以達到相同的目的;但是使用
System.Windows.Forms.Timer更簡單友善。在控件的構造函數中添加以下代碼:
public AnimateCtl()
{
//緩存 Graphics 對象
graphics = this.CreateGraphics();
//執行個體化 Timer
fTimer = new System.Windows.Forms.Timer();
//與 Timer 的 Tick 事件挂鈎
fTimer.Tick += new System.EventHandler(this.timer1_Tick);
}
在構造函數中,我們從控件的執行個體中緩存 Graphics 對象并建立一個新的 Timer 執行個體,然後将其與 Timer 的 Tick 事件挂鈎。現在已經可以插入
StartAnimation方法,以便實際啟動動畫:
public void StartAnimation(int frWidth, int DelayInterval, int LoopCount)
{
frameWidth = frWidth;
//循環次數
loopCount = LoopCount;
//重置循環計數器
loopCounter = 0;
//計算 frameCount
frameCount = bitmap.Width / frameWidth;
frameHeight = bitmap.Height;
//調整控件的大小
this.Size(frameWidth, frameHeight);
//向計時器指定延遲間隔
fTimer.Interval = DelayInterval;
//啟動計時器
fTimer.Enabled = true;
}
此方法接受一些非常重要的動畫參數:幀寬度、延遲間隔和循環次數。
另外,不要忘記循環邏輯:
private void timer1_Tick(object sender, System.EventArgs e)
{
if (loopCount == -1) //不停地循環
{
this.DrawFrame();
}
else
{
if (loopCount == loopCounter) //停止動畫
fTimer.Enabled = false;
else
this.DrawFrame();
}
}
private void DrawFrame()
{
if (currentFrame < frameCount-1)
{
//移到下一個幀
currentFrame++;
}
else
{
//遞增 loopCounter
loopCounter++;
currentFrame = 0;
}
Draw(currentFrame);
}
在上面代碼的
timer1_Tick事件中,我們檢查
loopCount以跟蹤已繪制的循環次數,并将其與調用
StartAnimation方法時捕獲的
loopCounter相比較。
演出開始!
我們已經完成了
AnimateCtl,現在可以進行測試。第一步,必須将帶有“故事闆”的圖像檔案添加到您的項目中。可以通過将此檔案變為嵌入的資源或僅通知 Visual Studio .NET 2003 将此檔案作為項目的一部分進行複制來完成此任務。在 Solution Explorer(解決方案資料總管)中的項目上單擊滑鼠右鍵,并在彈出式菜單中選擇
Add Existing Item...(添加現有項...)。浏覽到圖像檔案并確定此檔案的
Build Action(生成操作)屬性已被設定為
Content(内容)。
現在,在窗體的構造函數中插入以下代碼:
public Form1()
{
//
// Windows Form Designer(Windows 窗體設計器)支援所需
//
InitializeComponent();
//執行個體化控件
animCtl = new AnimateCtl();
//從圖像檔案指定 Bitmap
animCtl.Bitmap = new Bitmap(@"\Program
Files\AnimateControl\guestbk.gif");
//設定位置
animCtl.Location = new Point(50, 50);
//将控件添加到窗體
this.Controls.Add(animCtl);
}
在上面的代碼中,我們使用從圖像檔案中建立的 Bitmap 對象指定動畫控件的 Bitmap 屬性。
在設計器的窗體上放置兩個按鈕,并将以下代碼添加到它們的 Click 事件中:
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();
}
運作項目并點選 Start Animation(啟動動畫)按鈕,您就可以看到動畫了:
圖 3:最終産品僞動畫 GIF 檔案包含的幀的數目和幀之間的延遲時間可能會變化。當您為不同的動畫調用
StartAnimation方法時,需要調整
DelayInterval參數。
無論怎麼說,此代碼都不是最終版本。
AnimateCtl不能提供動畫 GIF 中包含的所有功能。例如,
AnimateCtl控件不能處理幀之間的不同延遲時間。例如,您可能希望第一幀顯示的時間比其他幀顯示的時間稍長一些。本文中的代碼對于您來說是一個很好的起點,您可以根據需要擴充此控件。
請記住,顯示高分辨率的圖形動畫将加重系統資源負擔。一定要注意運作此代碼的某些裝置的記憶體和資源限制。不要忘記進行全面測試,并確定應用程式既不會占用所有記憶體,也不會占用所有處理器時間。
小結雖然 .NET Framework 精簡版隻是 .NET Framework 完整版的一個子集,但是開發人員仍然可以建立對最終使用者更具吸引力的使用者界面。通過使用 .NET Framework 精簡版提供的 GIF 編輯器工具和繪圖能力,開發人員可以在其智能裝置項目中顯示動畫。