首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

利用 Visual C# 2005 實作 GDI+ 簡易動畫效果

     編輯:關於C#

Windows Forms 應用程式若需超越標準控制項的視覺表現,GDI+ 繪圖功能是最佳選擇。本文示範三種經典動畫效果——眨眼、彈跳球、文字閃爍——完整展示 System.Drawing 命名空間核心類別(Graphics、Bitmap、Brush、Font)與 Timer 定時器驅動重繪的實作模式。

專案架構與資源準備

  • 專案類型:Windows Application
  • 資源檔加入四張眼部圖片(Eye1~Eye4)供眨眼動畫使用
  • 表單載入時初始化資源陣列與組件資訊顯示
private Image[] arrImages = new Image[4];
private void Form_Load(object sender, EventArgs e)
{
    AssemblyInfoClass asm = new AssemblyInfoClass();
    this.Text = asm.AsmFQName;
    arrImages[0] = Properties.Resources.Eye1;
    arrImages[1] = Properties.Resources.Eye2;
    arrImages[2] = Properties.Resources.Eye3;
    arrImages[3] = Properties.Resources.Eye4;
}

關於對話盒實作

使用 VS2005 內建「關於方塊」範本,於 Load 事件填入組件中繼資料:

private void AboutBox_Load(object sender, EventArgs e)
{
    AssemblyInfoClass asm = new AssemblyInfoClass();
    labelProductName.Text = "產品名稱:" + asm.Product;
    labelVersion.Text = "版本:" + asm.Version;
    labelCopyright.Text = "版權宣告:" + asm.Copyright;
    labelCompanyName.Text = "公司名稱:" + asm.Company;
    textBoxDescription.Text = "細部描述:" + asm.Description;
}

選單項目叫用:new AboutBox().Show();

動畫模式切換邏輯

三個 RadioButton 控制項共用 CheckedChanged 事件,依選項設定 Timer.Interval 並觸發重繪:

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); // 觸發初始繪製
}

OnResize 重寫:場景初始化

protected override void OnResize(EventArgs ea)
{
    Graphics grfx = CreateGraphics();
    if (optWink.Checked)
    {
        this.Refresh(); // 眨眼模式僅需清空重繪
    }
    else if (optBall.Checked)
    {
        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);
        // 建立離屏位圖並繪製球體
        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 = ClientSize.Width / 2;
        intBallPositionY = ClientSize.Height / 2;
    }
    else if (optText.Checked)
    {
        grfx.Clear(BackColor); // 文字模式僅清空
    }
}

Timer.Tick 核心動畫迴圈

private void tmrAnimation_Tick(object sender, EventArgs e)
{
    Graphics grfx = CreateGraphics();
    
    // 1. 眨眼動畫:循環播放四張圖片
    if (optWink.Checked)
    {
        grfx.DrawImage(arrImages[intCurrentImage], 
            (ClientSize.Width - arrImages[intCurrentImage].Width) / 2,
            (ClientSize.Height - arrImages[intCurrentImage].Height) / 2);
        intCurrentImage += direction; // direction = 1 或 -1
        if (intCurrentImage == 3) direction = -1;
        else if (intCurrentImage == 0) direction = 1;
    }
    // 2. 彈跳球:更新位置、邊界檢測、碰撞反彈
    else if (optBall.Checked)
    {
        grfx.DrawImage(bitmap, 
            intBallPositionX - intBallBitmapWidth / 2,
            intBallPositionY - intBallBitmapHeight / 2);
        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();
        }
    }
    // 3. 文字閃爍:線性漸層筆刷位移產生流光效果
    else if (optText.Checked)
    {
        Font font = new Font("Microsoft Sans Serif", 48, FontStyle.Bold);
        string strText = "章立民研究室";
        SizeF textSize = grfx.MeasureString(strText, font);
        PointF textPos = new PointF((ClientSize.Width - textSize.Width) / 2, (ClientSize.Height - textSize.Height) / 2);
        PointF gradStart = new PointF(0, 0);
        PointF gradEnd = new PointF(intCurrentGradientShift, 200);
        LinearGradientBrush brush = new LinearGradientBrush(gradStart, gradEnd, Color.Blue, BackColor);
        grfx.DrawString(strText, font, brush, textPos);
        
        intCurrentGradientShift += intGradiantStep;
        if (intCurrentGradientShift == 500) intGradiantStep = -5;
        else if (intCurrentGradientShift == -50) intGradiantStep = 5;
    }
}

關鍵技術要點

  • 離屏繪圖:彈跳球使用 Bitmap + Graphics.FromImage 預先繪製球體,Tick 事件僅 DrawImage,減少閃爍。
  • 座標計算:結合 DpiX/DpiY 實現裝置獨立單位換算。
  • 漸層筆刷動畫:文字模式透過移動 LinearGradientBrush 端點座標產生流光閃爍。
  • 雙緩衝替代:簡易範例直接在 CreateGraphics() 繪製,正式專案建議啟用表單 DoubleBuffered = true 或繼承 Control 覆寫 OnPaint。

本範例展示 GDI+ 核心繪圖流程,可擴展至複雜遊戲迴圈、儀表板視覺化等場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved