如果程式在裝載時需要進行較長時間的處理,最好使用啟動畫面,一方面美化程式,一方面可以不使使用者面對著一片空白的程式介面。
我手頭上一個小項目主介面啟動時需要檢查使用者檔案及運行環境是否有效,需要一段時間處理,因此想到要添加一個啟動畫面,在網上搜了一陣,發現下面兩個方案:
1、用C#給程式加啟動畫面並只允許一個應用程式執行個體運行
http://www.zahui.com/html/14/36790.htm
2、HOW TO:濺射螢幕(Splash Screen),也叫程式啟動畫面的製作(.NET2003)
http://lzmtw.cnblogs.com/archive/2005/10/31/265782.html
第一個方案在實現與介面分離上做得不夠好,啟動介面(一個表單)依賴於特定表單,主表單還必須添加一個PreLoad方法完成裝載任務,只能在代碼級重用。而且那個只允許一個執行個體的寫法也太....
第二個方案架構很好,但細微處理可能存在一點問題,需要判斷主表單的WindowState,整個代碼也較複雜。
我改動了一下,基本結構仿照第二個方案。
功能:為程式添加啟動介面,顯示啟動介面的同時載入主表單,主表單載入完畢後關閉啟動介面,顯示主表單。啟動畫面停留的時間是設定的時間和主表單裝載所需時間兩個的最大值。啟動畫面在另一個線程上運行。
plus:我的水平還很差,見笑。
程式碼如下:
//啟動表單虛基類,繼承自ApplicationContext
using System.Windows.Forms;
using System.Threading;
using System;
//啟動畫面虛基類,啟動畫面會停留一段時間,該時間是設定的時間和主表單構造所需時間兩個的最大值
public abstract class SplashScreenApplicationContext : ApplicationContext
{
private Form _SplashScreenForm;//啟動表單
private Form _PrimaryForm;//主表單
private System.Timers.Timer _SplashScreenTimer;
private int _SplashScreenTimerInterVal = 5000;//預設是啟動表單顯示5秒
private bool _bSplashScreenClosed = false;
private delegate void DisposeDelegate();//關閉委託,下面需要使用控制項的Invoke方法,該方法需要這個委託
public SplashScreenApplicationContext()
{
this.ShowSplashScreen();//這裡建立和顯示啟動表單
this.MainFormLoad();//這裡建立和顯示啟動主表單
}
protected abstract void OnCreateSplashScreenForm();
protected abstract void OnCreateMainForm();
protected abstract void SetSeconds();
protected Form SplashScreenForm
{
set
{
this._SplashScreenForm = value;
}
}
protected Form PrimaryForm
{//在衍生類別中重寫OnCreateMainForm方法,在MainFormLoad方法中調用OnCreateMainForm方法
// ,在這裡才會真正調用Form1(主表單)的建構函式,即在啟動表單顯示後再調用主表單的建構函式
// ,以避免這種情況:主表單構造所需時間較長,在螢幕上許久沒有響應,看不到啟動表單
set
{
this._PrimaryForm = value;
}
}
protected int SecondsShow
{//未設定啟動畫面停留時間時,使用預設時間
set
{
if (value != 0)
{
this._SplashScreenTimerInterVal = 1000 * value;
}
}
}
private void ShowSplashScreen()
{
this.SetSeconds();
this.OnCreateSplashScreenForm();
this._SplashScreenTimer = new System.Timers.Timer(((double)(this._SplashScreenTimerInterVal)));
_SplashScreenTimer.Elapsed += new System.Timers.ElapsedEventHandler(new System.Timers.ElapsedEventHandler(this.SplashScreenDisplayTimeUp));
this._SplashScreenTimer.AutoReset = false;
Thread DisplaySpashScreenThread = new Thread(new ThreadStart(DisplaySplashScreen));
DisplaySpashScreenThread.Start();
}
private void DisplaySplashScreen()
{
this._SplashScreenTimer.Enabled = true;
Application.Run(this._SplashScreenForm);
}
private void SplashScreenDisplayTimeUp(object sender, System.Timers.ElapsedEventArgs e)
{
this._SplashScreenTimer.Dispose();
this._SplashScreenTimer = null;
this._bSplashScreenClosed = true;
}
private void MainFormLoad()
{
this.OnCreateMainForm();
while (!(this._bSplashScreenClosed))
{
Application.DoEvents();
}
DisposeDelegate SplashScreenFormDisposeDelegate = new DisposeDelegate(this._SplashScreenForm.Dispose );
this._SplashScreenForm.Invoke(SplashScreenFormDisposeDelegate);
this._SplashScreenForm = null;
//必須先顯示,再啟用,否則主表單不能在啟動表單消失後出現
this._PrimaryForm.Show();
this._PrimaryForm.Activate();
this._PrimaryForm.Closed += new EventHandler(_PrimaryForm_Closed);
}
private void _PrimaryForm_Closed(object sender, EventArgs e)
{
base.ExitThread();
}
}
使用方法:定義一個啟動類,應用程式從啟動類啟動,該類會使用繼承自啟動表單虛基類的一個啟動表單類,在該類中定義啟動表單和主表單。啟動表單和主表單的代碼略去,注意要刪除機器產生的表單代碼的Main方法部分。
public class StartUpClass
{
[STAThread]
static void Main()
{
Application.Run(new mycontext());
}
}
//啟動表單類(繼承自啟動表單虛基類),啟動畫面會停留一段時間,該時間是設定的時間和主表單構造所需時間兩個的最大值
public class mycontext : SplashScreenApplicationContext
{
protected override void OnCreateSplashScreenForm()
{
this.SplashScreenForm = new FormStart();//啟動表單
}
protected override void OnCreateMainForm()
{
this.PrimaryForm = new FormMain();//主表單
}
protected override void SetSeconds()
{
this.SecondsShow = 2;//啟動表單顯示的時間(秒)
}
}