2009-09-01 23 views
1

好吧,我知道這已被問過一百萬次之前(和人們也以XD的方式開始他們的StackOverflow問題),但我想知道如何實現如下:對於Winforms應用程序中的初始屏幕的不同要求

  1. 應用程序首先啓動一個登錄框
  2. 如果登錄成功,則啓動畫面必須顯示(在一個單獨的線程)。
  3. 在顯示啓動畫面時,必須填充一個類對象(這符合Singleton模式),其中包含大量來自DB的用戶特定數據,同時向用戶顯示它正在做什麼(例如,初始化。 .. loading data ... loading preferences ...渲染工作區...完成!)
  4. 啓動畫面還必須等待主窗體在主線程上完成初始化,然後才能最終處理。

這是應用程序的願望流。關閉主窗體後,用戶應該返回到登錄框。

我必須指出,我並不是所有的人都知道winforms的東西,但通過提出這些問題,我正在慢慢地學習。我一直在讀一些關於線程的知識,並且已經知道啓動屏幕應該在自己的線程中產生,並且使用委託(來迎合UI的交叉線程更新)爲主線程提供狀態更新,並且這應該全部在「Main()」子程序的Program.cs中完成。

由於登錄窗體先顯示(最後在Main窗體關閉時顯示),因此我甚至不知道從哪裏開始。我當然會重視這方面的任何協助。

非常感謝! sha

回答

2

下面是一個簡單的如何做到這一點的例子。訣竅是使登錄框成爲主窗體,因爲它是首先打開並關閉的窗體。

對於本示例,LoginScreen窗體有一個按鈕,一個OK按鈕,單擊時會調用OnOK()方法。

public partial class LoginScreen : System.Windows.Forms.Form 
{ 
    ApplicationWindow window; 

    public LoginScreen() 
    { 
     InitializeComponent(); 
    } 
    private void OnFormClosed(object sender, FormClosedEventArgs e) 
    { 
     this.Show(); 
    } 
    private void OnOK(object sender, EventArgs e) 
    { 
     this.Hide(); 

     window = new ApplicationWindow(); 
     window.FormClosed += OnFormClosed; 
     window.Show(); 
    } 
} 

ApplicationWindow窗體將等同於您所稱的「主」窗體。它是啓動SplashForm的。

public partial class ApplicationWindow : System.Windows.Forms.Form 
{ 
    public ApplicationWindow() 
    { 
     SplashForm.Show(500); 

     InitializeComponent(); 
    } 

    private void OnLoad(object sender, EventArgs e) 
    { 
     // Simulate doing a lot of work here. 
     System.Threading.Thread.Sleep(1000); 

     SplashForm.Hide(); 

     Show(); 
     Activate(); 
    } 
} 

這裏是我使用的SplashForm的副本。它將根據您在靜態Show()方法中指定的毫秒數來淡入和淡出。

public partial class SplashForm : Form 
{ 
    #region Public Methods 

    /// <summary> 
    /// Shows the splash screen with no fading effects. 
    /// </summary> 
    public new static void Show() 
    { 
     Show(0); 
    } 

    /// <summary> 
    /// Shows the splash screen. 
    /// </summary> 
    /// <param name="fadeTimeInMilliseconds">The time to fade 
    /// in the splash screen in milliseconds.</param> 
    public static void Show(int fadeTimeInMilliseconds) 
    { 
     // Only show the splash screen once. 
     if (_instance == null) { 
      _fadeTime = fadeTimeInMilliseconds; 
      _instance = new SplashForm(); 

      // Hide the form initially to avoid any pre-paint flicker. 
      _instance.Opacity = 0; 
      ((Form) _instance).Show(); 

      // Process the initial paint events. 
      Application.DoEvents(); 

      if (_fadeTime > 0) { 
       // Calculate the time interval that will be used to 
       // provide a smooth fading effect. 
       int fadeStep = (int) Math.Round((double) _fadeTime/20); 
       _instance.fadeTimer.Interval = fadeStep; 

       // Perform the fade in. 
       for (int ii = 0; ii <= _fadeTime; ii += fadeStep) { 
        Thread.Sleep(fadeStep); 
        _instance.Opacity += 0.05; 
       } 
      } else { 
       // Use the Tag property as a flag to indicate that the 
       // form is to be closed immediately when the user calls 
       // Hide(); 
       _instance.fadeTimer.Tag = new object(); 
      } 

      _instance.Opacity = 1; 
     } 
    } 

    /// <summary> 
    /// Closes the splash screen. 
    /// </summary> 
    public new static void Hide() 
    { 
     if (_instance != null) { 
      // Invoke the Close() method on the form's thread. 
      _instance.BeginInvoke(new MethodInvoker(_instance.Close)); 

      // Process the Close message on the form's thread. 
      Application.DoEvents(); 
     } 
    } 

    #endregion Public Methods 

    #region Constructors 

    /// <summary> 
    /// Initializes a new instance of the SplashForm class. 
    /// </summary> 
    public SplashForm() 
    { 
     InitializeComponent(); 

     Size = BackgroundImage.Size; 

     // If transparency is ever needed, set the color of the desired 
     // transparent portions of the bitmap to fuschia and then 
     // uncomment this code. 
     //Bitmap bitmap = new Bitmap(this.BackgroundImage); 
     //bitmap.MakeTransparent(System.Drawing.Color.Fuchsia); 
     //this.BackgroundImage = bitmap; 
    } 

    #endregion Constructors 

    #region Protected Methods 

    protected override void OnClosing(CancelEventArgs e) 
    { 
     base.OnClosing(e); 

     // Check to see if the form should be closed immediately. 
     if (fadeTimer.Tag != null) { 
      e.Cancel = false; 
      _instance = null; 
      return; 
     } 

     // Only use the timer to fade if the form is running. 
     // Otherwise, there will be no message pump. 
     if (Application.OpenForms.Count > 1) { 
      if (Opacity > 0) { 
       e.Cancel = true; // prevent the form from closing 
       Opacity -= 0.05; 

       // Use the timer to iteratively call the Close method. 
       fadeTimer.Start(); 
      } else { 
       fadeTimer.Stop(); 

       e.Cancel = false; 
       _instance = null; 
      } 
     } else { 
      if (Opacity > 0) { 
       Thread.Sleep(fadeTimer.Interval); 
       Opacity -= 0.05; 
       Close(); 
      } else { 
       e.Cancel = false; 
       _instance = null; 
      } 
     } 
    } 

    #endregion Protected Methods 

    #region Private Methods 

    private void OnTick(object sender, EventArgs e) 
    { 
     Close(); 
    } 

    #endregion Private Methods 

    #region Private Fields 

    private static SplashForm _instance = null; 
    private static int _fadeTime = 0; 

    #endregion Private Fields 
} 

的SplashForm只是一個空白窗體具有以下屬性值:

  • 的BackgroundImage =(您所選擇的圖像)
  • BackgroundImageLayout =中心
  • DoubleBuffered =真
  • FormBorderStyle =無
  • ShowInTaskbar = False
  • 中StartPosition =中心屏幕
  • 最頂層=真

它還包含一個名爲fadeTimer與默認性能System.Windows.Forms.Timer控制。 Tick事件被配置爲調用OnTick()方法。

這不能做的是更新加載過程的狀態。也許別人可以爲你填寫那部分內容。

+0

這不會在單獨的線程中運行Splash Form,但另一個鏈接應該有幫助。 – 2009-09-01 20:07:26

+0

要與Splash Screen進行通信,可以在ApplicationWindow上監聽事件,或者加載過程定期調用啓動畫面上的方法。如果啓動畫面在單獨的線程中,請記住使用BeginInvoke。 – 2009-09-01 20:08:47

+0

你說得對。自從我看過這段代碼以來已經有一段時間了。我會更新我的帖子以保持正確。謝謝。 – 2009-09-01 20:59:08