3
votes

I have a splash screen for my C# database application that is called via the Shown event. The splash screen contains some information that is preprocessed when the main form's constructor is called, hence why I'm using the Shown event, because that information should be available.

However, when the splash screen is shown, the main form is whited out, and the menu bar, bottom menu bar, and even the gray background are all white and invisible. It looks like the program is hanging, but after the 5 second delay I have built in, the banner goes away and the program is shown normally. Also, on the banner, I have labels that are not shown when the splash screen displays...

Here is my code, some reasoning behind why it isn't working would help greatly.

SPLASH SCREEN CODE :

public partial class StartupBanner : Form
{
    public StartupBanner(int missingNum, int expiredNum)
    {
        InitializeComponent();
        missingLabel.Text = missingNum.ToString() + " MISSING POLICIES";
        expiredLabel.Text = expiredNum.ToString() + " EXPIRED POLICIES";
    }
}

CALLING CODE :

    private void MainForm_Shown(object sender, EventArgs e)
    {
        StartupBanner startup = new StartupBanner(missingPoliciesNum, expiredPoliciesNum);
        startup.MdiParent = this;
        startup.Show();

        Thread.Sleep(5000);
        startup.Close();
    }

Using startup.ShowDialog() shows the correct label information on the splash screen, but that locks up the application, and I need the splash to go away after about 5 seconds, which is why it's a splash. ;)

4
A splash screen doesn't mean "a useless banner that shows up for 5 seconds". Do the necessary initialization while the splash screen is showing, and then get it off the screen as soon as possible. These suggestions to use a timer and wait for some arbitrarily defined interval are simply inane. Please don't do this.Cody Gray

4 Answers

6
votes

First run the splash screen with ShowDialog() instead of Show(), so the splashscreen locks the main form and do not lock the main thread:

private void MainForm_Shown(object sender, EventArgs e)
{
    StartupBanner startup = new StartupBanner(missingPoliciesNum, expiredPoliciesNum);
    startup.ShowDialog();
}

In the splash screen form you should define a timer that closes the form after 5 seconds:

public partial class StartupBanner : Form
{
    private System.Windows.Forms.Timer _closeTimer = new Timer();

    public StartupBanner(int missingNum, int expiredNum)
    {
        this.InitializeComponent();
        missingLabel.Text = missingNum.ToString() + " MISSING POLICIES";
        expiredLabel.Text = expiredNum.ToString() + " EXPIRED POLICIES";

        this._closeTimer = new System.Windows.Forms.Timer();
        this._closeTimer.Interval = 5000;
        this._closeTimer.Tick += new EventHandler(this._closeTimer_Tick);
        this._closeTimer.Start();
    }

    private void _closeTimer_Tick(object sender, EventArgs e)
    {
        System.Windows.Forms.Timer timer = (System.Windows.Forms.Timer)sender;
        timer.Stop();

        this.Close();
    }
}

EDIT: Thread.Sleep() locks the whole thread e.g. each action for the forms, so that they cannot handle any message like clicks or button presses. They do not run in background, so it is better to use a timer that can close the form in background.

FIX: removed startup.MdiParent = this; line

2
votes

It is a feature of Windows, designed to help the user cope with unresponsive programs. When you display the splash screen, Windows sends your main form a message to tell it that it is no longer the active window. This normally causes it to redraw the window caption, using the color for inactive windows. That same message also fires the Form.Deactivated event.

But that doesn't work anymore, your main thread is busy executing code and not going idle to 'pump the message loop'. Windows notices this, the message isn't getting delivered. After a couple of seconds, it replaces your window with the 'ghost window'. It has the same size and border as your main window but with no content, just a white background. And a caption that reads "Not responding". Enough for the user to know that trying to use the window isn't going to work.

Avoid this by using a real splash screen, support for it is already built into .NET.

0
votes

In your code, MainForm_Shown wait 'Thread.Sleep(5000);', so it got white because the main thread sleep and couldn't get any message. The StartupBanner Form have some reason, too. I suggest you use Thread to avoid sub function or sub thread intercepting main thread and make MainForm whited out.

-1
votes

There is inbuild support for splashscreens in .Net

The best way and using the API is

  SplashScreen splash = new SplashScreen("splashscreen.jpg");
  splash.Show(false);
  splash.Close(TimeSpan.FromMilliseconds(2));
  InitializeComponent();