Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# WinForm - loading screen

I would like to ask how to make a loading screen (just a picture or something) that appears while the program is being loaded, and disappears when the program has finished loading.

In fancier versions, I have seen the process bar (%) displayed. how can you have that, and how do you calculate the % to show on it?

I know there is a Form_Load() event, but I do not see a Form_Loaded() event, or the % as a property / attribute anywhere.

like image 630
CaTx Avatar asked Apr 05 '13 14:04

CaTx


3 Answers

all you need to create one form as splash screen and show it before you main start showing the landing page and close this splash once the landing page loaded.

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

and the main program function looks like this:

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

Don't forget to add a form load event to your main form:

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

It will bring the main form to the foreground after hiding the splash screen.

like image 183
JSJ Avatar answered Oct 17 '22 16:10

JSJ


I had problem with all other solutions I found, specially those that show splash in other thread than gui thread and specially on Citrix.

Example:

  • Splash never closes
  • Splash show on wrong monitor
  • Splash show ok but mainform is showing behind all other windows

I ended up with this and it seems to work well.

Splash form:

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

    private void pictureBox1_Click(object sender, EventArgs e)
    {

    }
}

Splash form cont:

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

Main:

[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();
}
like image 20
osexpert Avatar answered Oct 17 '22 18:10

osexpert


If you're going to show the SplashForm more than once in your application, be sure to set the splashForm variable to null otherwise you'll get an error.

static private void CloseFormInternal()
{
    splashForm.Close();
    splashForm = null;
}
like image 1
TheJonz Avatar answered Oct 17 '22 16:10

TheJonz