winforms 应用程序中对启动屏幕的不同要求

发布于 2024-08-03 08:53:04 字数 592 浏览 9 评论 0原文

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

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

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

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

我在这里伸出援手,因为我什至不知道从哪里开始,因为需要首先显示登录表单(然后在主表单关闭时最后显示)。我当然非常重视这方面的任何帮助。

非常感谢! 煞

Ok, I know this has been asked a million times before (and people also start off their StackOverflow question in the very same way XD), but I would like to know how to achieve the following:

  1. The application first launches a login box
  2. If the login is successful, then the splash screen must show (on a separate thread).
  3. While the splash screen is showing, a class object must be filled (that adheres to the Singleton pattern) with copious amounts of user-specific data from the DB, whilst displaying back to user what it is doing (eg. initializing...loading data...loading preferences...rendering workspace...done!)
  4. The splash screen must also wait for the main form to finish initializing on the main thread, before finally being disposed of.

That is the desire flow for the application. Upon closing the main form, the user should be returned to the login box.

I must state upfront that I am not all that clued up on alot of winforms stuff, but through asking these kind of questions, I am slowly learning. I have been doing some reading up on threading, and have learned that the splash screen should be spawned in its own thread, and feed status updates using delegates (to cater for cross-thread updates to the UI) from the main thread, and that this should all be done in the Program.cs "Main()" subroutine.

I am reaching out here, as I don't even know where to begin, due to the additional requirement of having the login form show first (and then last when the Main form is closed). I would certainly value any assistance in this regard.

Much thanks!
sha

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

对风讲故事 2024-08-10 08:53:04

下面是如何执行此操作的简单示例。诀窍是让登录框成为您的主窗体,因为它是第一个打开并最后关闭的窗体。

对于本示例,LoginScreen 表单有一个按钮,即“确定”按钮,单击该按钮时将调用 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 = Center
  • DoubleBuffered = true
  • FormBorderStyle = None
  • ShowInTaskbar = False
  • StartPosition = CenterScreen
  • TopMost = true

它还包含一个 System.Windows.Forms。名为 fadeTimer 的计时器控件,具有默认属性。 Tick 事件配置为调用 OnTick() 方法。

这不会更新加载过程的状态。也许其他人可以为您填写该部分。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文