14

我想问一下如何制作一个加载屏幕(只是一张图片或其他东西),在程序加载时出现,在程序加载完成时消失。

在更高级的版本中,我看到了显示的进程栏 (%)。你怎么能有它,你如何计算要显示的百分比?

我知道有一个 Form_Load() 事件,但我没有看到 Form_Loaded() 事件,或者在任何地方都没有看到 % 作为属性/属性。

4

5 回答 5

38

您只需要创建一个表单作为启动屏幕并在您开始显示登录页面之前显示它,并在登录页面加载后关闭此启动页面。

using System.Threading;
using System.Windows.Forms;

namespace MyTools
{
    public class SplashForm : Form
    {
        //Delegate for cross thread call to close
        private delegate void CloseDelegate();

        //The type of form to be displayed as the splash screen.
        private static SplashForm splashForm;

        static public void ShowSplashScreen()
        {
            // Make sure it is only launched once.    
            if (splashForm != null) return;
            splashForm = new SplashScreen();
            Thread thread = new Thread(new ThreadStart(SplashForm.ShowForm));
            thread.IsBackground = true;
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        static private void ShowForm()
        {
            if (splashForm != null) Application.Run(splashForm);
        }

        static public void CloseForm()
        {
            splashForm?.Invoke(new CloseDelegate(SplashForm.CloseFormInternal));
        }

        static private void CloseFormInternal()
        {
            if (splashForm != null)
            {
               splashForm.Close();
               splashForm = null;
            };
        }
    }
}

主程序功能如下所示:

[STAThread]
static void Main(string[] args)
{
    SplashForm.ShowSplashScreen();
    MainForm mainForm = new MainForm(); //this takes ages
    SplashForm.CloseForm();
    Application.Run(mainForm);
}

不要忘记在主表单中添加表单加载事件:

private void MainForm_Load(object sender, EventArgs e)
{
    this.WindowState = FormWindowState.Minimized; 
    this.WindowState = FormWindowState.Normal;
    this.Focus(); this.Show();
}

隐藏启动画面后,它将把主窗体带到前台。

于 2013-04-05T14:09:22.863 回答
2

我发现的所有其他解决方案都有问题,特别是那些在 gui 线程之外的其他线程中显示飞溅的解决方案,特别是在 Citrix 上。

例子:

  • 飞溅永远不会关闭
  • 在错误的显示器上闪现
  • 启动画面正常,但主窗体显示在所有其他窗口后面

我最终得到了这个,它似乎运作良好。

飞溅形式:

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

    private void pictureBox1_Click(object sender, EventArgs e)
    {

    }
}

飞溅形式续:

partial class Splash
{
    private System.ComponentModel.IContainer components = null;

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    private void InitializeComponent()
    {
        System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Splash));
        this.pictureBox1 = new System.Windows.Forms.PictureBox();
        ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
        this.SuspendLayout();
        // 
        // pictureBox1
        // 
        this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
        this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
        this.pictureBox1.Location = new System.Drawing.Point(0, 0);
        this.pictureBox1.Name = "pictureBox1";
        this.pictureBox1.Size = new System.Drawing.Size(512, 224);
        this.pictureBox1.TabIndex = 0;
        this.pictureBox1.TabStop = false;
        this.pictureBox1.Click += new System.EventHandler(this.pictureBox1_Click);
        // 
        // Splash
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(512, 224);
        this.ControlBox = false;
        this.Controls.Add(this.pictureBox1);
        this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
        this.Name = "Splash";
        this.ShowIcon = false;
        this.ShowInTaskbar = false;
        this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
        this.Text = "Splash";
        ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.PictureBox pictureBox1;
}

主要的:

[STAThread]
static void Main(string[] _args)
{
    ShowSplash();
    MainForm mainForm = new MainForm();
    Application.Run(mainForm);
}

private static void ShowSplash()
{
    Splash sp = new Splash();
    sp.Show();
    Application.DoEvents();

    System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
    t.Interval = 1000;
    t.Tick += new EventHandler((sender, ea) =>
    {
        sp.BeginInvoke(new Action(() =>
        {
            if (sp != null && Application.OpenForms.Count > 1)
            {
                sp.Close();
                sp.Dispose();
                sp = null;
                t.Stop();
                t.Dispose();
                t = null;
            }
        }));
    });
    t.Start();
}
于 2018-04-25T09:19:31.847 回答
1

如果您要在应用程序中多次显示 SplashForm,请务必将 splashForm 变量设置为 null,否则会出现错误。

static private void CloseFormInternal()
{
    splashForm.Close();
    splashForm = null;
}
于 2014-03-12T17:00:51.730 回答
0

这是打开应用程序时执行加载屏幕的一种更简单的方法。

async private void Form1_Shown(object sender, EventArgs e)
            {
                pictureBox1.Visible = true;
                await Task.Delay(2000);
                pictureBox1.Visible = false;
    
            }
于 2020-12-23T05:02:40.190 回答
0

你也可以使用这个...(表单的名称是“Home.cs”)

await Task.Delay(10000);
this.Hide();          
Home h1 = new Home();
h1.ShowDialog();
        

并在表单的属性中:Windowstate: Normal; Controlbox: False; ImeMode: NoControl

于 2021-01-28T10:25:14.550 回答