Click here to Skip to main content
Click here to Skip to main content

.NET Splash Screen Component

, 23 Oct 2008 CC (ASA 2.5)
Rate this:
Please Sign up or sign in to vote.
A splash screen which allows for dynamic creation and updates.

Introduction

Well, after scouring the Internet for a free splash screen component for .NET, I was left quite unhappy. The only decent ones around were by a company called BitLaboratory, and another CodeProject article published by Mr. Tom Clemont (link).

I had used BitLab's component previously, and was not overwhelmed with its design ... and they would not release the source. :/

So, here I was in the middle of several projects which all needed a splash page. And, I'm not one for your basic static splash screen. I like to show the user what's going on in the background. So, here is my DGDev - a splash screen assembly.

Background

The basic ideas I wanted to implement:

  • Threading
  • Custom background image
  • Custom product/program information space
  • Custom space for updated status
  • Custom splash screen form shape (TransparencyKey)

Mr. Clemont's example served as a nice reference, but this has been entirely written from scratch.

Example

screenshot.jpg

  • ScreenCam for the project implementation: Click here.

Full code

The actual code is very short, and very clear to understand.

using System;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace DGDev
{
    public class SplashScreen : Form
    {
        private const double OpacityDecrement = .08;
        private const double OpacityIncrement = .05;
        private const int TimerInterval = 50;
        private static Boolean FadeMode;
        private static Boolean FadeInOut;
        private static Image BGImage;
        private static String Information;
        private static String Status;
        private static SplashScreen SplashScreenForm;
        private static Thread SplashScreenThread;
        private static Color TransparentKey;
        private Label ProgramInfoLabel;
        private Label StatusLabel;
        private System.Windows.Forms.Timer SplashTimer;
        private IContainer components;
        private delegate void UpdateLabel();
        private delegate void CloseSplash();

        #region Public Properties & Methods

        /// <summary>
        /// These methods can all be called to set configurable 
                  /// parameters for the Splash Screen
        /// </summary>
        public String SetInfo
        {
            get { return Information; }
            set
            {
                Information = value;
                if(ProgramInfoLabel.InvokeRequired)
                {
                    var InfoUpdate = 
                        new UpdateLabel(UpdateInfo);
                    Invoke(InfoUpdate);
                }
                else
                {
                    UpdateInfo();
                }
            }
        }

        public String SetStatus
        {
            get { return Status; }
            set
            {
                Status = value;
                if(StatusLabel.InvokeRequired)
                {
                    var StatusUpdate = 
                        new UpdateLabel(UpdateStatus);
                    Invoke(StatusUpdate);
                }
                else
                {
                    UpdateStatus();
                }
            }
        }

        public Image SetBackgroundImage
        {
            get { return BGImage; }
            set
            {
                BGImage = value;
                if (value != null)
                {
                    BackgroundImage = BGImage;
                    ClientSize = BackgroundImage.Size;
                }
            }
        }

        public Color SetTransparentKey
        {
            get { return TransparentKey; }
            set
            {
                TransparentKey = value;
                if (value != Color.Empty)
                    TransparencyKey = SetTransparentKey;
            }
        }

        public Boolean SetFade
        {
            get { return FadeInOut; }
            set
            {
                FadeInOut = value;
                Opacity = value ? .00 : 1.00;
            }
        }

        public static SplashScreen Current
        {
            get
            {
                if (SplashScreenForm == null)
                    SplashScreenForm = new SplashScreen();
                return SplashScreenForm;
            }
        }

        public void SetStatusLabel(Point StatusLabelLocation, 
                Int32 StatusLabelWidth, Int32 StatusLabelHeight)
        {
            if (StatusLabelLocation != Point.Empty)
                StatusLabel.Location = StatusLabelLocation;
            if (StatusLabelWidth == 0 && StatusLabelHeight == 0)
                StatusLabel.AutoSize = true;
            else
            {
                if (StatusLabelWidth > 0)
                    StatusLabel.Width = StatusLabelWidth;
                if (StatusLabelHeight > 0)
                    StatusLabel.Height = StatusLabelHeight;
            }
        }

        public void SetInfoLabel(Point InfoLabelLocation, 
                Int32 InfoLabelWidth, Int32 InfoLabelHeight)
        {
            if (InfoLabelLocation != Point.Empty)
                ProgramInfoLabel.Location = InfoLabelLocation;
            if (InfoLabelWidth == 0 && InfoLabelHeight == 0)
                ProgramInfoLabel.AutoSize = true;
            else
            {
                if (InfoLabelWidth > 0)
                    ProgramInfoLabel.Width = InfoLabelWidth;
                if (InfoLabelHeight > 0)
                    ProgramInfoLabel.Height = InfoLabelHeight;
            }
        }

        public void ShowSplashScreen()
        {
            SplashScreenThread = new Thread(ShowForm) 
                {IsBackground = true, Name = "SplashScreenThread"};
            SplashScreenThread.Start();
        }

        public void CloseSplashScreen()
        {
            if (SplashScreenForm != null)
            {
                if(InvokeRequired)
                {
                    var ClosingDelegate = 
                        new CloseSplash(HideSplash);
                    Invoke(ClosingDelegate);
                }
                else
                {
                    HideSplash();
                }
            }
        }
        #endregion

        public SplashScreen()
        {
            InitializeComponent();
        }

        private static void ShowForm()
        {
            Application.Run(SplashScreenForm);
        }

        private void UpdateStatus()
        {
            StatusLabel.Text = SetStatus;
        }

        private void UpdateInfo()
        {
            ProgramInfoLabel.Text = SetInfo;
        }

        private void SplashTimer_Tick(object sender, EventArgs e)
        {
            if(FadeMode) // Form is opening (Increment)
            {
                if (Opacity < 1.00)
                    Opacity += OpacityIncrement;
                else
                    SplashTimer.Stop();
            }
            else // Form is closing (Decrement)
            {
                if(Opacity > .00)
                    Opacity -= OpacityDecrement;
                else
                    Dispose();
            }
            
        }

        #region InitComponents

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.ProgramInfoLabel = new System.Windows.Forms.Label();
            this.StatusLabel = new System.Windows.Forms.Label();
            this.SplashTimer = new System.Windows.Forms.Timer
                            (this.components);
            this.SuspendLayout();
            // 
            // ProgramInfoLabel
            // 
            this.ProgramInfoLabel.BackColor = 
                    System.Drawing.Color.Transparent;
            this.ProgramInfoLabel.Location = 
                    new System.Drawing.Point(56, 52);
            this.ProgramInfoLabel.Name = "ProgramInfoLabel";
            this.ProgramInfoLabel.Size = 
                    new System.Drawing.Size(100, 23);
            this.ProgramInfoLabel.TabIndex = 0;
            // 
            // StatusLabel
            // 
            this.StatusLabel.BackColor = 
                    System.Drawing.Color.Transparent;
            this.StatusLabel.Location = 
                    new System.Drawing.Point(59, 135);
            this.StatusLabel.Name = "StatusLabel";
            this.StatusLabel.Size = new System.Drawing.Size(100, 23);
            this.StatusLabel.TabIndex = 1;
            // 
            // SplashScreen
            // 
            this.ClientSize = new System.Drawing.Size(292, 273);
            this.Controls.Add(this.StatusLabel);
            this.Controls.Add(this.ProgramInfoLabel);
            this.FormBorderStyle = 
                System.Windows.Forms.FormBorderStyle.None;
            this.Name = "SplashScreen";
            this.ShowInTaskbar = false;
            this.StartPosition = 
                System.Windows.Forms.FormStartPosition.CenterScreen;
            this.ResumeLayout(false);

        }

        #endregion

        private void SplashScreen_Load(object sender, EventArgs e)
        {
            if (SetFade)
            {
                FadeMode = true;
                SplashTimer.Interval = TimerInterval;
                SplashTimer.Start();
            }
        }

        private void HideSplash()
        {
            if(SetFade)
            {
                FadeMode = false;
                SplashTimer.Start();
            }
            else
                Dispose();
        }
    }
}

Using the DLL

Let's take a quick glimpse at another program I'm working on, which is now fit for using the splash screen.

Program.cs

using System;
using System.Drawing;
using System.Windows.Forms;
using DGDev;

namespace Raum
{
    static class Program
    {
        private static SplashScreen splash;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            const String resourceName = "Splash.png";
            var InfoLabel = new Point(25, 92);
            var StatusLabel = new Point(28, 261);

            splash = SplashScreen.Current;
            splash.SetTransparentKey = Color.Fuchsia;
            var rs = GetResourceStream(resourceName);
            splash.SetBackgroundImage = new Bitmap(rs);
            splash.SetInfoLabel(InfoLabel, 499, 117);
            splash.SetStatusLabel(StatusLabel, 490, 17);
            splash.ShowSplashScreen();
            splash.SetInfo = "This program is just an example.";

            AppDomain currentDomain = AppDomain.CurrentDomain;
            currentDomain.AssemblyLoad += asmLoadHandler;

            Application.Run(new RaumMain());
        }

        private static System.IO.Stream GetResourceStream(String resource)
        {
            var ea = System.Reflection.Assembly.GetExecutingAssembly();
            foreach (String curResource in ea.GetManifestResourceNames())
            {
                if (curResource.EndsWith(resource))
                {
                    return ea.GetManifestResourceStream
                                (curResource);
                }
            }
            return null;
        }

        static void asmLoadHandler(object sender, AssemblyLoadEventArgs args)
        {
            splash.SetStatus = "Loading Assembly: " + 
                args.LoadedAssembly.GetName().Name + " ...";
        }
    }
}

A closer look

So, what's going on up there?!? By using this SplashScreen.dll, you can literally have your splash screen done in a minute, with several options to play with.

// This will be our BackgroundImage of the Splash
const String resourceName = "Splash.png";  
// This creates a Location point for our ProgramInfo label.
var InfoLabel = new Point(25, 92);  
// This creates a Location point for our Status label.
var StatusLabel = new Point(28, 261);  

// You must call this before attempting to assign any properties! 
// It creates/initializes all the form controls. 
splash = SplashScreen.Current; 

// Say you want a custom shape Splash Screen. 
// You can use this to set the TransparencyKey. 
splash.SetTransparentKey = Color.Fuchsia; 

// Call our function to pull the image from our Resources.resx
var rs = GetResourceStream(resourceName); 
// Set the Splash BackgroundImage
splash.SetBackgroundImage = new Bitmap(rs); 

//This method uses 3 parameters. (Point Location, Int32 Width, Int32 Height)
//If you set both Width & Height to 0, than the label will set AutoSize = true. 
//Default is false.

splash.SetInfoLabel(InfoLabel, 499, 117);

splash.SetStatusLabel(StatusLabel, 490, 17); // Same as above, but for the Status Label

splash.ShowSplashScreen();  // You must call this to RUN the Splash Screen 
splash.SetInfo = "This program is just an example.";

Dynamically loading updates

By preference, I like to show the user what .NET assemblies are being loaded. Here, we see that whenever an assembly is loaded, it updates the status label on the splash screen.

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyLoad += asmLoadHandler;

static void asmLoadHandler(object sender, AssemblyLoadEventArgs args)
{
    splash.SetStatus = "Loading Assembly: " + 
            args.LoadedAssembly.GetName().Name + " ...";
}

Closing the splash screen

A great feature about this class is that it can be accessed from anywhere in your code. So, after your Main form has loaded, just use the following to close the splash screen:

splash = SplashScreen.Current;
splash.CloseSplashScreen();

Points of interest

Known issues:

  • When using a custom shape form/TransparencyKey, you cannot use the SetFade property. If you do, you'll notice that the TransparencyKey does not work until the Form.Opacity is at 1.00.

Questions/Problems/Suggestions

I have not yet implemented try/catch blocks, so exceptions are not being handled at the moment. Will do more testing, and add new features along with proper exception handling.

If you have a problem, feel free to email me, or post in the discussion forum below.

If you're using this for proprietary commercial software, help a broke college student out and donate a dollar.

History

  • 10.13.2008 - v1.0.0.0 released.
  • 10.24.2008 2:05pm - Fixed the demo download link. Sorry guys.
  • 10.23.2008 4:42pm - Uploaded new files. There were a few bugs to be fixed. Code should now work with all .NET Framework versions. Also, the SetFade is fixed.
  • 10.13.2008 10:08pm - Sorry guys, after refactoring the code automatically with JetBrains, it took away some needed assembly constructors in the designer code. Reshaper tends to think everything is redundant, sometimes. I've updated the fixed file.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License

Share

About the Author

Anon1234567890

United States United States
No Biography provided

Comments and Discussions

 
Questionre-Show the ScreenPlash PinmemberBlowdesign23-Nov-09 4:47 
AnswerRe: re-Show the ScreenPlash PinmemberDGDev23-Nov-09 6:00 
QuestionRe: re-Show the ScreenPlash PinmemberBlowdesign25-Nov-09 0:42 
GeneralError when starting project after crash Pinmemberdauciunas11-Nov-09 4:24 
GeneralRe: Error when starting project after crash PinmemberDGDev11-Nov-09 6:32 
GeneralRe: Error when starting project after crash Pinmemberdauciunas11-Nov-09 12:17 
GeneralTerminating the splash screen PinmemberImpero10116-Sep-09 9:49 
Generalok article PinmemberDonsw4-Feb-09 6:31 
GeneralRe: ok article PinmemberDGDev4-Feb-09 21:19 
Will try to do that in the future...
However I do not suggest following this article anymore.
 
Please visit:
http://www.dgdev.net/products/software/advanced-splash-screen-component-for-net/[^]
 
This is a complete redo of the Splash Screen component and is far better. I will be implementing a few new features to it as well in the coming days...
 
It's 100% FREE, but I do accept any donations if you think its well deserved.
You can find thorough documentation within the download zip file and online at:
 
http://www.dgdev.net/documentation/advancedsplashscreen/[^]
 
Select the "Enterprise" edition to obtain the zip which contains the VS project files and source code.
 
Thanks again everyone for your responses and email me with any questions at daniel@dgdev.net
 
DGDev

GeneralSTOP USING THIS COMPONENT! [modified] PinmemberDGDev16-Dec-08 15:13 
GeneralRe: STOP USING THIS COMPONENT! PinmemberLery782-Jul-09 9:07 
GeneralRe: STOP USING THIS COMPONENT! PinmemberDGDev11-Nov-09 6:32 
GeneralRe-use splash PinmemberDennis Sheppard5-Dec-08 9:18 
GeneralThis is very nice! Pinmemberdataporter2-Nov-08 10:34 
QuestionWinapp Main form hiding behind another open window Pinmemberokash24-Oct-08 0:25 
AnswerRe: Winapp Main form hiding behind another open window PinmemberDGDev24-Oct-08 9:15 
Generaldemo project broken link PinmemberMichal Stehlik23-Oct-08 23:33 
GeneralRe: demo project broken link PinmemberDGDev24-Oct-08 9:15 
GeneralFade Pinmemberlagdaemon23-Oct-08 10:40 
GeneralRe: Fade PinmemberDGDev23-Oct-08 11:52 
QuestionThis Part did not work Pinmembermaabd22-Oct-08 17:37 
AnswerRe: This Part did not work PinmemberDGDev22-Oct-08 17:55 
QuestionWPF ? PinmemberLoic Berthollet21-Oct-08 3:19 
GeneralNo demo project and no screenshot PinmemberJohnny J.13-Oct-08 22:15 
GeneralRe: No demo project and no screenshot PinmemberDGDev14-Oct-08 0:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411023.1 | Last Updated 23 Oct 2008
Article Copyright 2008 by Anon1234567890
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid