Click here to Skip to main content
15,861,125 members
Articles / Programming Languages / C++
Article

Own-thread Win32 splash screen

Rate me:
Please Sign up or sign in to vote.
4.49/5 (25 votes)
20 Jun 2008CDDL2 min read 125.2K   7.1K   111   15
Implementation of an own-thread splash screen, with a progress indicator using Win32 and GDI+.

Sample screenshot

Introduction

Using MFC-based classes -- even with your own threads -- may lead to hang-up of the splash screen repainting while loading the application. This is because MFC has synchronization on the message queue level. So, the application stops responding to the user. CSplashWnd is a class that makes it easy to use splash screens that can always paint themselves. It is implemented using the Win32 API, but you can use it in MFC applications, as well.

How to Use the Class

The CSplashWnd uses GDI+ to show images. It allows you to use a variety of image types including BMP, GIF, JPEG, PNG, TIFF and EMF. However, you have to initialize the GDI+ library:

C++
// Before using CSplashWnd

GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

...

// Somewhere in the end of your program

GdiplusShutdown(gdiplusToken);

The use of CSplashWnd is very simple. Just add SplashWnd.cpp and SplashWnd.h into your project and then include SplashWnd.h in your program. To initialize the splash screen, use CSplashWnd::SetImage. This method sets the image you want to see while loading the application. It can look like this:

C++
...

CSplashWnd splash;
splash.SetImage(pImage);
splash.Show();

// ... Some long operation


splash.Hide();

...

The splash screen can have a button on the taskbar. It is created only if CSplashWnd::SetWindowName is invoked before CSplashWnd::Show. A button on the taskbar may be useful if the splash screen appears before any window is created. In that case, the user can easily find the application. You can indicate the loading progress using the CSplashWnd::SetProgress method. The first call of CSplashWnd::SetProgress leads to creating a progress control at the bottom of the splash window. It also sets the progress control to the initial state. All subsequent calls just update the progress state.

You could show more details of loading or computing process by passing text description of progress stage to CSplashWnd::SetProgress method using text string or string resource ID as additional input parameter.

C++
...

splash.Show()
splash.SetProgress(0, L"Loading...");

for (int i =0; i < 100; ++i)
{
  // compute something

  // ...

  splash.SetProgress(i);
}

splash.SetProgress(100, L"Done.");

...

If the length of the loading operation is known, you'll want to use the CSplashWnd::SetAutoProgress method. It automatically updates the progress state using its own timer. At the moment, it updates the state one step per second. The previous code will now look like:

C++
...

splash.Show()
splash.SetAutoProgress(0, 100, 100);

for (int i =0; i < 100; ++i)
{
  // compute something

  // here we know that one loop takes one second

}

...

History

  • August 9, 2006 - The class was written.
  • May 25, 2007 - Some synchronization has been added and the timer message ID has been fixed.
  • June 20, 2008 - New features: multimonitor support, text progress status, support for external resource handles.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
Software Developer
Russian Federation Russian Federation
Just another developer.

Comments and Discussions

 
QuestionDoesnt work in x64? Pin
Member 1017777329-Jul-13 13:09
Member 1017777329-Jul-13 13:09 
AnswerRe: Doesnt work in x64? Pin
Kirill V. Lyadvinsky4-Aug-13 18:23
Kirill V. Lyadvinsky4-Aug-13 18:23 
Questionvisual studio 2010 release build Pin
AlhajiBello29-Sep-12 8:30
AlhajiBello29-Sep-12 8:30 
AnswerRe: visual studio 2010 release build Pin
Kirill V. Lyadvinsky1-Oct-12 7:32
Kirill V. Lyadvinsky1-Oct-12 7:32 
AnswerRe: visual studio 2010 release build Pin
AlhajiBello1-Oct-12 21:46
AlhajiBello1-Oct-12 21:46 
Thanks for trying.

The problem is this:

Gdiplus::Image* pImage = Gdiplus::Image::FromFile("blah.jpg");
if(pImage == 0)


If the image can't be found pImage will not be 0, so the Messagebox isn't displayed.

Here are the respective values in pImage:

1. Loaded image
pImage {nativeImage=0x003943b8 lastResult=Ok loadStatus=-1163005939 }

2. Failed to load image
pImage {nativeImage=0x00000000 lastResult=OutOfMemory loadStatus=-1163005939 }

Replacing
if(pImage == 0)

with

if(pImage->GetLastStatus() != Gdiplus::Ok)

worked for me.
GeneralAdded code to getImage from resource Pin
Member 78479692-Jun-11 8:14
Member 78479692-Jun-11 8:14 
QuestionAnimated Gif Support Pin
T.Haberkern30-Jun-07 8:32
T.Haberkern30-Jun-07 8:32 
AnswerRe: Animated Gif Support Pin
Ștefan-Mihai MOGA20-Jun-08 14:28
professionalȘtefan-Mihai MOGA20-Jun-08 14:28 
GeneralCompile example with Studio2003 Pin
Ben_AH4-Jun-07 23:36
Ben_AH4-Jun-07 23:36 
GeneralI can't see the progress bar in the sample project Pin
AlexZherdev24-May-07 12:18
AlexZherdev24-May-07 12:18 
GeneralRe: I can't see the progress bar in the sample project [modified] Pin
Kirill V. Lyadvinsky24-May-07 20:38
Kirill V. Lyadvinsky24-May-07 20:38 
GeneralAbitlity to run exe on a separated thread Pin
john Pure27-Sep-06 7:47
john Pure27-Sep-06 7:47 
GeneralRe: Abitlity to run exe on a separated thread Pin
Kirill V. Lyadvinsky28-Sep-06 21:37
Kirill V. Lyadvinsky28-Sep-06 21:37 
GeneralBackground of my application Pin
AlexEvans19-Sep-06 13:06
AlexEvans19-Sep-06 13:06 
GeneralRe: Background of my application Pin
Kirill V. Lyadvinsky19-Sep-06 21:17
Kirill V. Lyadvinsky19-Sep-06 21:17 

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

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