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

C# WinForms 啟動畫面 實作完整指南

     編輯:關於C#

啟動畫面能提升應用程式感知效能,掩蓋初始化延遲。本文介紹標準實作模式:主視窗載入時以對話框模式顯示啟動畫面,配合 Timer 或背景工作執行初始化,完成後自動關閉。

標準三步驟實作

1. Program.cs:應用程式進入點

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }
}

2. MainForm.cs:主視窗載入時顯示啟動畫面

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    private void MainForm_Load(object sender, EventArgs e)
    {
        // 以對話框模式顯示啟動畫面(阻塞主視窗顯示)
        using (var splash = new SplashForm())
        {
            splash.ShowDialog(this); // 設定 Owner 確保置中顯示
        }

        // 啟動畫面關閉後,繼續主視窗初始化或直接進入應用
        InitializeMainForm();
    }

    private void InitializeMainForm()
    {
        // 載入設定、連接資料庫、初始化模組等耗時操作
        // 建議改為非同步初始化,避免凍結 UI
    }
}

3. SplashForm.cs:啟動畫面邏輯

public partial class SplashForm : Form
{
    private readonly System.Windows.Forms.Timer _timer;
    private int _progress = 0;

    public SplashForm()
    {
        InitializeComponent();
        ConfigureForm();
        InitializeTimer();
    }

    private void ConfigureForm()
    {
        // 關鍵:無邊框、無標題列、置中顯示
        this.FormBorderStyle = FormBorderStyle.None;
        this.StartPosition = FormStartPosition.CenterParent; // 相對 Owner 置中
        this.ShowInTaskbar = false;
        this.TopMost = true; // 確保顯示在最上層
        
        // 設定背景圖片
        this.BackgroundImage = Properties.Resources.SplashScreen; // 從資源載入
        this.BackgroundImageLayout = ImageLayout.Stretch;
        this.ClientSize = this.BackgroundImage.Size;
    }

    private void InitializeTimer()
    {
        _timer = new System.Windows.Forms.Timer { Interval = 100 };
        _timer.Tick += Timer_Tick;
    }

    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);
        _timer.Start();
        
        // 或在背景執行緒執行初始化工作
        Task.Run(PerformInitialization);
    }

    private async void PerformInitialization()
    {
        try
        {
            // 模擬初始化步驟
            await InitializeDatabaseAsync();
            ReportProgress(30, "資料庫連線完成");
            
            await LoadConfigurationAsync();
            ReportProgress(60, "設定載入完成");
            
            await InitializeModulesAsync();
            ReportProgress(90, "模組初始化完成");
            
            await FinalizeStartupAsync();
            ReportProgress(100, "啟動完成");
        }
        catch (Exception ex)
        {
            // 記錄錯誤,決定是否繼續或中止
            ReportProgress(100, $"初始化失敗:{ex.Message}");
        }
    }

    private void ReportProgress(int percent, string message)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(() => ReportProgress(percent, message));
            return;
        }
        
        _progress = percent;
        lblStatus.Text = message;
        progressBar.Value = percent;
        
        if (percent >= 100)
        {
            _timer.Stop();
            // 短暫延遲讓使用者看完 100%
            await Task.Delay(500);
            this.Close();
        }
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        // 動畫效果:閃爍標誌、旋轉圖示等
        lblLoading.Visible = !lblLoading.Visible;
    }

    protected override void OnFormClosed(FormClosedEventArgs e)
    {
        _timer?.Stop();
        _timer?.Dispose();
        base.OnFormClosed(e);
    }

    // 模擬初始化方法
    private Task InitializeDatabaseAsync() => Task.Delay(800);
    private Task LoadConfigurationAsync() => Task.Delay(600);
    private Task InitializeModulesAsync() => Task.Delay(1000);
    private Task FinalizeStartupAsync() => Task.Delay(300);
}

進階:非同步啟動畫面模式

避免阻塞主執行緒,使用 `Show` 而非 `ShowDialog`,配合 `Task` 協調:

public partial class MainForm : Form
{
    private SplashForm _splash;

    public MainForm()
    {
        InitializeComponent();
        this.Load += MainForm_Load;
        this.Shown += MainForm_Shown;
    }

    private async void MainForm_Load(object sender, EventArgs e)
    {
        _splash = new SplashForm();
        _splash.Show(this); // 非阻塞顯示
        
        // 並行執行:UI 動畫 + 後端初始化
        await Task.WhenAll(
            _splash.RunAnimationAsync(),
            InitializeApplicationAsync()
        );
        
        _splash.Close();
        _splash.Dispose();
    }

    private async Task InitializeApplicationAsync()
    {
        // 真實初始化工作
        await Task.Delay(2000); 
    }
}

public partial class SplashForm : Form
{
    public async Task RunAnimationAsync()
    {
        while (this.Visible && !this.IsDisposed)
        {
            // 更新動畫
            await Task.Delay(100);
        }
    }
}

關鍵屬性設定對照表

| 屬性 | 建議值 | 用途 | |------|--------|------| | `FormBorderStyle` | `None` | 無邊框,純圖片顯示 | | `StartPosition` | `CenterParent` | 相對主視窗置中 | | `ShowInTaskbar` | `false` | 不在工作列顯示 | | `TopMost` | `true` | 確保不被其他視窗遮擋 | | `BackgroundImage` | 專用圖片 | 品牌標識、版本資訊、載入動畫 | | `TransparencyKey` | (可選) | 配合 PNG 透明背景實現異形視窗 |

最佳實踐清單

  • ✅ 圖片內嵌為資源,避免部署路徑問題
  • ✅ 使用 `async/await` 非同步初始化,不凍結動畫
  • ✅ 顯示具體進度訊息,降低使用者焦慮
  • ✅ 設定最小顯示時間(如 1-2 秒),避免閃現
  • ✅ 錯誤處理:初始化失敗時顯示錯誤並提供重試/退出選項
  • ✅ 高 DPI 支援:圖片提供 100%/125%/150%/200% 多版本
  • ✅ 記憶體管理:關閉時正確 `Dispose` 圖片與 Timer

現代替代:WPF / MAUI / Blazor Hybrid

  • WPF:`SplashScreen` 類別原生支援、像素著色器動畫
  • .NET MAUI:跨平台啟動畫面 API (`MauiSplashScreen`)
  • Blazor Hybrid:Web 技術實現豐富動畫,共用 Web 資產

啟動畫面是使用者體驗的第一印象,投入適度精力實作專業的啟動體驗,能顯著提升應用程式的感知品質。

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