1

好的,我知道这已经被问过一百万次了(人们也以同样的方式开始他们的 StackOverflow 问题 XD),但我想知道如何实现以下目标:

  1. 应用程序首先启动一个登录框
  2. 如果登录成功,则必须显示初始屏幕(在单独的线程上)。
  3. 在显示初始屏幕时,必须使用来自数据库的大量用户特定数据填充类对象(遵循单例模式),同时向用户显示它正在做什么(例如,初始化...加载数据...加载首选项...渲染工作区...完成!)
  4. 启动画面还必须等待主窗体在主线程上完成初始化,然后才能最终被处理掉。

这就是应用程序的需求流。关闭主窗体后,用户应返回到登录框。

我必须预先声明,我对很多 winforms 的东西并不是很了解,但是通过提出这些问题,我正在慢慢学习。我一直在阅读有关线程的内容,并了解到启动屏幕应该在其自己的线程中生成,并使用主线程的委托(以迎合 UI 的跨线程更新)提供状态更新,并且这一切都应该在Program.cs “Main()”子例程中完成。

我在这里联系,因为我什至不知道从哪里开始,因为首先显示登录表单(然后在主表单关闭时最后显示)的附加要求。我当然会重视这方面的任何帮助。

非常感谢!沙

4

1 回答 1

2

Here's a simple example of how to do this. The trick is to make the login box your main form since it's the one that opens first and closes last.

For this example, the LoginScreen form has one button, an OK button that invokes the OnOK() method when clicked.

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();
    }
}

The ApplicationWindow form would equate to what you referred to as your "main" form. It is what launches the 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();
    }
}

And here's a copy of the SplashForm I use. It will fade in and fade out based on the number of milliseconds you specify in the static Show() method.

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
}

The SplashForm is just a blank form with the following property values:

  • BackgroundImage = (the image of your choice)
  • BackgroundImageLayout = Center
  • DoubleBuffered = true
  • FormBorderStyle = None
  • ShowInTaskbar = False
  • StartPosition = CenterScreen
  • TopMost = true

It also contains a System.Windows.Forms.Timer control named fadeTimer with the default properties. The Tick event is configured to invoke the OnTick() method.

What this does not do is update the status of the loading process. Perhaps someone else can fill in that portion for you.

于 2009-09-01T19:59:00.197 回答