Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Splash Screen with Semitransparent Borders

0.00/5 (No votes)
17 Nov 2007 1  
This article shows how to create a Splash Screen with alpha-channel image and semitransparent borders.
Screenshot - Article.png

Introduction

Due to the increased starting time of my application, I needed to display the loading status, i.e. splash screen. I examined splash screens in several programs and chose the one that is used by Adobe Acrobat Reader 6. Splash screens with transparent, founded "regions" have sharp borders, like holes in windows.
Certain types have a principal feature � smooth borders of the picture on the screen. But they also have some bugs:

  • When another window moves above the splash screen, an image may be lost
  • If the underlying picture (e.g. the color/text of the window or other controls) was changed, we can see an abnormal border (the part of the background at the time when the splash screen was displayed). This type of splash screen was created by an algorithm (IMHO): before showing off the splash screen, the program makes a screenshot of the desktop, draws a picture with alpha-channel on it, and places the result on splash screen forms
  • Sometimes this appears as a hung application

For example, a splash screen of this type with an abnormal border is shown below:

Example of abnormal border of splash screen

Then I found an article, OSD Window With Animation Effect, in C# by Mr.Smarty and concluded that it is a great idea. I modified the source to add the capability to change the text and image when the window is already on the screen.
Thank you very much, Mr. Smarty!

Using the Code

Before being displayed, the SplashScreen creates the application's main form, shows a window and passes it to the constructor of the main form.

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    SplashScreen splash = new SplashScreen();
    splash.Show();
    Application.Run(new FormMain(splash));
}

We can call the SetProgress method for an update of status progress on the splash screen in the constructor of the main form. For example:

public partial class FormMain : Form
{
    public FormMain(SplashScreen splash)
    {
        mSplashScreen = splash;
        mSplashScreen.SetProgress("Initialize Components...", 0.0);
        InitializeComponent();
        mSplashScreen.SetProgress("Some task 1...", 0.2);
        Thread.Sleep(1000);
        mSplashScreen.SetProgress("Some task 2...", 0.4);
        Thread.Sleep(1000);
        mSplashScreen.SetProgress("Some task 3...", 0.6);
        Thread.Sleep(1000);
        mSplashScreen.SetProgress("Some task 4...", 0.8);
        Thread.Sleep(1000);
        mSplashScreen.SetProgress("Starting...", 1.0);
    }
    private SplashScreen mSplashScreen;
...

In the above code snippet, Thread.Sleep is an emulation of continuous operations.

When the main form is ready to be displayed, we have to close the splash screen:

private void FormMain_Load(object sender, EventArgs e)
{
    if (mSplashScreen != null)
        mSplashScreen.Hide();
}

The appearance of the splash screen realizes in the function FormWelcome.PerformPaint.

protected override void PerformPaint(PaintEventArgs e)
{
    if (base.Handle != IntPtr.Zero)
    {
        Graphics g = e.Graphics;
        g.SmoothingMode = SmoothingMode.HighQuality;

        //background (png with alpha-channel)

        g.FillRectangle(this.mBrush, this.Bound);

        //text

        g.DrawString(String.Format("{0} v{1}", Application.ProductName,
            Application.ProductVersion), mTextFont, mTextBrush, 40, 20);
        g.DrawString(mMessageText, SystemFonts.DialogFont, mTextBrush,
            40, this.Height - 40);

        //progress bar

        float w = this.Width - 10 * 2;
        //g.DrawLine(mPenProgress, 40, this.Height - 20, 40 + w *

            mCompletionFraction, this.Height - 20);
        g.DrawImageUnscaledAndClipped(
            Properties.Resources.image_load_progress_texture,
            new Rectangle(10, 36, (int)(w * mCompletionFraction),
                Properties.Resources.image_load_progress_texture.Height));
    }
}

Points of Interest

  • Before OSD, I tried to create the splash screen as a Form in a separate thread, but this method didn't solve the problem with abnormal borders when the background changes. However, if we have a rectangle image, this method can be useful.
  • I found that drawing the alpha-channel images with tiles over the other images with gradient gives an interesting effect and applied it for drawing the progress bar.
  • I also tried another method unlike that of the splash screen: we can create only the main Form of an application with the progress bar, and create (asynchronously) another interface on a dedicated UserControl after showing the main Form on the screen.

History

  • 31/8/2007 - v1.0 First release

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here