摘要:Visual C# 2005 - 如何利用程式碼製作簡單動畫效果
一般的 Windows Form 通常是運用各種控制項來顯示資料,然而如果您希望在表單中加入特殊效果來凸顯資料內容,則圖形與動畫將是非常不錯的選擇。
一般來說,我們會使用 .Net Framework中 的 GDI+ 函式庫來製作圖形與動畫效果。在 GDI+ 還沒有推出之前,如果要產生二維的 向量圖形、影像、以及印刷樣式,必須使用舊版作業系統中的GDI。新的 GDI+ 是 Windows XP 的一部份,除了加入新功能之外,還最佳化現有功能以便具體改進 GDI(也就是舊版 Windows 包含的繪圖裝置介面)的效能。
程式範例
圖表1
圖表2
圖表3
我們的程式範例示範了三種動畫效果,分別是:眨眼效果、彈跳的球、以及文字閃爍,當程式執行時會自動展示第一種眨眼效果,如圖表1到3所示。
運用之前「如何利用程式碼動態存取組件資訊」的技巧,將組件的 AsmFQName 屬性值指派給表單的 Text 屬性,並將先前已經加入專案資源的四張圖片名稱指派給陣列,之後就使用此陣列來示範眨眼效果,程式碼撰寫於表單的Load事件處理常式中,如下所示:
private void Blog_DemoForm002_Load(object sender, EventArgs e)
{
AssemblyInfoClass myAssembly = new AssemblyInfoClass();
this.Text = myAssembly.AsmFQName;
// 指派陣列成員。
arrImages[0] = Properties.Resources.Eye1;
arrImages[1] = Properties.Resources.Eye2;
arrImages[2] = Properties.Resources.Eye3;
arrImages[3] = Properties.Resources.Eye4;
}
圖表4
如果您要使用 Visual C# 來製作「關於」對話方塊,建議先使用Visual Studio 2005所提供的範本來產生關於對話方塊表單,然後再自訂表單所要呈現的內容(如圖表4所示)。在此,我們選擇將組件的相關資訊填入表單對應的控制項,請於「關於」對話方塊表單的 Load 事件處理常式中撰寫下列程式碼:
private void AboutBox_Load(object sender, EventArgs e)
{
AssemblyInfoClass myAssembly = new AssemblyInfoClass();
labelProductName.Text = "產品名稱:" + myAssembly.Product;
labelVersion.Text = "版本:" + myAssembly.Version;
labelCopyright.Text = "版權宣告:" + myAssembly.Copyright;
labelCompanyName.Text = "公司名稱:" + myAssembly.Company;
textBoxDescription.Text = "細部描述:" +
myAssembly.Description;
}
要顯示「關於」對話方塊,請替「說明」功能表項目的Click事件處理常式中撰寫下列程式碼:
private void toolStripMenuItem4_Click(
object sender, EventArgs e)
{
// 顯示關於對話方塊。
AboutBox MyAboutBox = new AboutBox();
// 設定關於對話方塊的啟始位置。
MyAboutBox.StartPosition = FormStartPosition.CenterScreen;
MyAboutBox.Show();
}
當使用者點選不同的選項按鈕時,將會執行下列程式碼來顯示不同的動畫效果。這些程式碼撰寫於選項按鈕的 CheckedChanged 事件處理函式中,如下所列:
private void RadioButtons_CheckedChanged(object sender,
EventArgs e)
{
if(optWink.Checked)
{
tmrAnimation.Interval = WINK_TIMER_INTERVAL;
}
else if(optBall.Checked)
{
tmrAnimation.Interval = BALL_TIMER_INTERVAL;
}
else if(optText.Checked)
{
tmrAnimation.Interval = TEXT_TIMER_INTERVAL;
}
OnResize(EventArgs.Empty);
}
自訂函式 RadioButtons_CheckedChanged 會叫用 OnResize 函式來產生不同的圖形,請大家注意,我們係使用 Graphics 類別的 FillEllipse 方法來繪製球形,程式碼如下所列:
protected override void OnResize(EventArgs ea)
{
if (optWink.Checked)
{
Graphics grfx = CreateGraphics();
// 重繪表單。
this.Refresh();
}
else if (optBall.Checked)
{
Graphics grfx = CreateGraphics();
grfx.Clear(BackColor);
double dblRadius = Math.Min(ClientSize.Width / grfx.DpiX,
ClientSize.Height / grfx.DpiY) / intBallSize;
intBallRadiusX = (int)(dblRadius * grfx.DpiX);
intBallRadiusY = (int)(dblRadius * grfx.DpiY);
intBallMoveX =
(int)(Math.Max(1, intBallRadiusX / intMoveSize));
intBallMoveY =
(int)(Math.Max(1, intBallRadiusY / intMoveSize));
intBitmapWidthMargin = intBallMoveX;
intBitmapHeightMargin = intBallMoveY;
intBallBitmapWidth =
2 * (intBallRadiusX + intBitmapWidthMargin);
intBallBitmapHeight =
2 * (intBallRadiusY + intBitmapHeightMargin);
bitmap = new Bitmap(intBallBitmapWidth, intBallBitmapHeight);
grfx = Graphics.FromImage(bitmap);
grfx.Clear(BackColor);
// 繪製球形。
grfx.FillEllipse(
Brushes.Red, new Rectangle(intBallMoveX,
intBallMoveY, 2 * intBallRadiusX, 2 * intBallRadiusY));
intBallPositionX = (int)(ClientSize.Width / 2);
intBallPositionY = (int)(ClientSize.Height / 2);
}
else if (optText.Checked)
{
Graphics grfx = CreateGraphics();
grfx.Clear(BackColor);
}
}
最後,利用計時器將圖形連續重繪於表單上,便產生了動畫效果。程式碼撰寫於計時器的 Tick 事件處理常式中,如下所示:
private void tmrAnimation_Tick(object sender, EventArgs e)
{
// 眨眼效果。
if(optWink.Checked)
{
Graphics grfx = CreateGraphics();
// 將陣列中之圖形繪製在畫面上。
grfx.DrawImage(arrImages[intCurrentImage],
(int)(
(ClientSize.Width - arrImages[intCurrentImage].Width) / 2),
(int)
((ClientSize.Height -
arrImages[intCurrentImage].Height) / 2),
arrImages[intCurrentImage].Width,
arrImages[intCurrentImage].Height);
intCurrentImage += j;
if(intCurrentImage == 3)
{
j = -1;
}
else if(intCurrentImage == 0)
{
j = 1;
}
}
else if(optBall.Checked) // 彈跳的球。
{
Graphics grfx = CreateGraphics();
// 將球繪製在畫面上。
grfx.DrawImage(bitmap,
(int)(intBallPositionX - intBallBitmapWidth / 2),
(int)(intBallPositionY - intBallBitmapHeight / 2),
intBallBitmapWidth, intBallBitmapHeight);
// 移動球的位置。
intBallPositionX += intBallMoveX;
intBallPositionY += intBallMoveY;
// 球碰到左右邊界。
if(intBallPositionX + intBallRadiusX >= ClientSize.Width ||
intBallPositionX - intBallRadiusX <= 0)
{
intBallMoveX = -intBallMoveX;
SystemSounds.Beep.Play();
}
// 球碰到上下邊界。
if(intBallPositionY + intBallRadiusY >= ClientSize.Height ||
intBallPositionY - intBallRadiusY <= 75)
{
intBallMoveY = -intBallMoveY;
SystemSounds.Beep.Play();
}
}
else if (optText.Checked) // 閃動文字。
{
Graphics grfx = CreateGraphics();
// 設定文字的字型與大小。
Font font = new Font("Microsoft Sans Serif", 48, FontStyle.Bold,
GraphicsUnit.Point);
// 設定要顯示的文字。
string strText = "章立民研究室";
SizeF sizfText = new SizeF(grfx.MeasureString(strText, font));
// X座標與Y座標的配對。
PointF ptfTextStart = new PointF(
(float)(ClientSize.Width - sizfText.Width) / 2,
(float)(ClientSize.Height - sizfText.Height) / 2);
PointF ptfGradientStart = new PointF(0, 0);
PointF ptfGradientEnd =
new PointF(intCurrentGradientShift, 200);
// 設定筆刷。
LinearGradientBrush grBrush = new LinearGradientBrush(
ptfGradientStart, ptfGradientEnd, Color.Blue, BackColor);
// 將文字繪製在畫面上。
grfx.DrawString(strText, font, grBrush, ptfTextStart);
// 以不同的座標繪製文字,造成閃動效果。
intCurrentGradientShift += intGradiantStep;
if (intCurrentGradientShift == 500)
{
intGradiantStep = -5;
}
else if (intCurrentGradientShift == -50)
{
intGradiantStep = 5;
}
}
}