C# WinForm - loading screen
Asked Answered
A

5

15

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.

Abshier answered 5/4, 2013 at 14:5 Comment(2)
What does the form load? Do you have any database query operations, cpu-intensive operations,something you really need to show a "progress bar" or do you just want a splash screen?Enterotomy
I want a splash screen, but I also want to know about the progress bar.Abshier
R
44

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.

Retiring answered 5/4, 2013 at 14:9 Comment(14)
Can I use this code to call a big and slow form from another form? Like a Login -> Main Screen?Inefficacy
your mainScreen is the startup point for your programe process. so you need an alive instance of main then you can.Retiring
I know this is a little old. But I am having issue with the splash screen code above if my main form loads very quickly (NullRefEx on splashForm). I assume this is because ShowSplashScreen has not finished creating the separate thread before CloseForm is called?Oldham
exception hendling not done under CloseFormInternal function. you can check if splashform is not null then only close form.Retiring
I have an issue using this approach. After main form is loaded, it close the splash as expected. But when Application.Run(mainForm); kicks in, the main form is shown behind whatever application currently on focus... i.e. when launching the app by running exe file from explorer, splash screen is shown in front of explorer, but main form is shown behind explorer. Any idea why?Midmost
Kurotsuki: I have the same problem. But no solutionSplitlevel
There is something in your code that is always resetting the form to a default blank square form. No matter what design elements I add to it, it isn't showing up.Venu
I found out what's lacking. Default constructor and InitializeComponent();Venu
I got it working but it is impossible to have any dynamic design element on a static form. I tried everything but every time got stuck at "Object reference not set to an instance of an object". Can you please show how to solve this issue?Venu
What do you do if it can be launched multiple times and you can't satisfy this condition: // Make sure it is only launched once.Faulk
I edited the solution as added a constructor. You need to create a form as you like then replace the code like here, then voila! It works like a charm. Protip: Make an invisible border and add a picture box in it. Insert a gif in the picture box. That's all folks!Gaptoothed
public SplashForm() { InitializeComponent(); } This should also be added inside the class to make it work.Gaptoothed
@Kurotsuki - Late answer, but I was able to solve it: Create a Form_Load event for the main screen and inside it do the following: this.WindowState = FormWindowState.Minimized; this.WindowState = FormWindowState.Normal; this.Focus(); this.Show();Messiaen
I've added some improvements regarding null-handling, and added hint for MainForm_Load event.Messiaen
S
3

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();
}
Splitlevel answered 25/4, 2018 at 9:19 Comment(0)
M
1

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;
}
Matherly answered 12/3, 2014 at 17:0 Comment(0)
H
0

Here is a much simpler way of doing a loading screen when opening the application.

async private void Form1_Shown(object sender, EventArgs e)
            {
                pictureBox1.Visible = true;
                await Task.Delay(2000);
                pictureBox1.Visible = false;
    
            }
Hysterogenic answered 23/12, 2020 at 5:2 Comment(0)
A
0

You can also use this... (the name of the form is "Home.cs")

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

And in the properties of the form: Windowstate: Normal; Controlbox: False; ImeMode: NoControl

Aleron answered 28/1, 2021 at 10:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.