Animated Multithread Splash

Friday Feb 11th 2005 by zheng chen

Build a real multithreaded splash, with the slow loading process and the animated splash running simultaniously.

A snapshot of the Shutter style splash

Splash is useful in many applications, especially in some slow-loading processes. There is a splash screen in Visual C++ ATL, but it has many useless functions and is somehow rigid. So, you can create a flexible splash.

To create the multithread splash, you can refer to the article "A Splash Screen with Alpha Blending," written by Leonardo Bernardini. In it, maybe there is something different from my splash class, but they are both based on the same technique.

How It Works

If you are not interested in it, you can skip this section and go to the next section, where you can learn how to use it.

As you can see, the splash screen is in fact a window without a title bar and board. So, you create a window to draw what you want.

You derive CUltraSplashWnd from the CWnd class and add a member function to create a real window: The first part creates an invisible window used as the parent so that the splash window won't show in the task bar. Here is the code:

BOOL CUltraSplashWnd::Create()
   //Create an invisible parent window
   LPCTSTR pszWndClass = AfxRegisterWndClass(0);

   //Create splash window
      m_bm.bmWidth,      //Width of bitmap
      m_bm.bmHeight,     //Height of bitmap

   ShowCursor(FALSE);    //Hide the cursor
   m_bClose = false;

   return TRUE;

You use Show() to begin drawing.

void CUltraSplashWnd::Show()
   while (!m_bClose)

As you can see, this loop forces a redraw of the window, so that the animation can display. The animation implements in OnPaint(). You must create a memory DC to store the splash bitmap. After that, you check the animation style and jump to the corresponding drawing function.

void CUltraSplashWnd::OnPaint()
   CPaintDC dc(this);    // device context for painting
   m_pDC = &dc;
   //TODO: Add your message handler code here
      m_MemDC.CreateCompatibleDC(&dc);    //Create the memory DC to
                                          //store the bitmap
      m_MemDC.SelectObject(&m_bitmap);    //Select the bitmap to
                                          //the DC

   bool bOver = false;

      switch (m_nStyle)
      case USS_LEFT2RIGHT:     //left to right
         bOver = Left2Right(m_CtrlVal1);
      case USS_RIGHT2LEFT:     //right to left
         bOver = Right2Left(m_CtrlVal1);
      case USS_UP2DOWN:        //up to down
         bOver = Up2Down(m_CtrlVal1);
      case USS_DOWN2UP:        //down to up
         bOver = Down2Up(m_CtrlVal1);
      case USS_HORISHUTTER:    //horizontal shutter
         bOver = HoriShutter(m_CtrlVal1,m_CtrlVal2);
      case USS_VERTSHUTTER:    //vertical shutter
         bOver = VertShutter(m_CtrlVal1,m_CtrlVal2);
      case USS_RANDOMBOX:      //random box
         bOver = RandomBox(m_CtrlVal3);
         //Static drawing, copy picture to dc directly
         m_pDC->BitBlt(0, 0, m_bm.bmWidth, m_bm.bmHeight, &m_MemDC,
                       0, 0, SRCCOPY);

      //set style to static after animated
      if (bOver) m_nStyle = USS_STATIC;

      // Do not call CWnd::OnPaint() for painting messages

For example: If you render the splash bitmap left to right, you use the function as follows:

The render process is controlled by some member variables. The drawing functions use a reference to these control variables. Each calls the drawing function adds the control variable to 1, so it draws one column of the bitmap each time. When drawing to the right side, the function returns true and the style is set to static.

bool CUltraSplashWnd::Left2Right(int &i)
   if (i<m_bm.bmWidth)
      m_pDC->BitBlt(i, 0, 1, m_bm.bmHeight, &m_MemDC, i, 0, SRCCOPY);
      return false;
      return true;

I just wrote seven drawing styles, it's easy to add your own drawing algorithm into the class. But, don't forget to initialize your control variables in SetStyle() and set the STYLE_COUNT to the styles' count.

How to Use

First of all, you can download the source files and add them into your app, which includes:

  • UltraSplash.cpp, UltraSplash.h
  • UltraSplashThread.cpp, UltraSplashThread.h
  • UltraSplashWnd.cpp, UltraSplashWnd.h

Now, you must include one header into your project; in general, you can paste the following code to your Application Class that derived from CWinApp:

//insert the header into your project
#include "UltraSplash.h"

Then, insert the following codes before the slow loading:

CUltraSplash splash;
splash.ShowSplash(IDB_BITMAP1, USS_RANDOM);

IDB_BITMAP1 is the ID of the bitmap resource. You can change IDB_BITMAP1 to any picture you like. Also, you can use a picture filename as the first parameter. The second parameter is an animation-style enumeration; you can find the enumeration at the top of the UltraSplashWnd.h file.

After the busy loading, you can hide the splash by using splash.HideSplash().

  • If your application is modal dialog-based, you would like to release the splash object by using splash.Destory(); before the call of DoModal().
  • If your application is another type, you would like to do nothing and the splash class can release itself in the destructor.

You must note that the call of HideSplash() just hides the splash window rather than destroys it. And, the call of marco Destory() not only releases the splash thread but also implicitly sets the focus to the main window. So, if you you don't want to call the Destroy(), add this line:


to set the focus to the main window, and the splash object will released in the destructor. After that, you can press F5 to see the result.

Note: To active the main window (the default is that the main window is set to the bottom of the z-order), I divide the hiding and destroying into two parts, HideSplash just hides the splash window; the Destroy method implicitly calls the DestroySplash(m_pMainhWnd). Before closing the splash screen, you set the Main window to the top. Maybe there is a better method to solve this problem.

In the end, as I said, I am a beginner and this my first article with CodeGuru. So, if you spot something that is incorrect in this code or you have any questions, please let me know by e-mailing me at: endether@hotmail.com.

Mobile Site | Full Site
Copyright 2018 © QuinStreet Inc. All Rights Reserved