Splash Screen with 256 color support

The Developer Studio in Visual C++ has a Splash Screen component that you can insert using the Component Galery. Unfortunately, this component supports only 16 colors. I have yet to see a commercial application that uses a 16 color splash screen. There might be a few software using a 16 color splash screen but I haven't seen one yet. The code given below is for a splash screen that supports 256 color and is very easy to use. Step 1: Create the splash window class To make the implementation of the splash screen modular it is best to create a new class for it. The CMySplashWnd class derives from CWnd. The header and the implementation file listings are given below.

#if !defined(AFX_MYSPLASHWND_H__08C608F3_1FB3_11D1_830E_58A47E000000__INCLUDED_)
#define AFX_MYSPLASHWND_H__08C608F3_1FB3_11D1_830E_58A47E000000__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// MySplashWnd.h : header file

// CMySplashWnd window

class CMySplashWnd : public CWnd
// Construction
    CMySplashWnd(UINT nBitmapID, UINT nDuration = 2500);

// Attributes
    BOOL Create();

// Operations

// Overrides
	// ClassWizard generated virtual function overrides
	virtual BOOL PreTranslateMessage(MSG* pMsg);

// Implementation

	// Generated message map functions
	afx_msg void OnPaint();
	afx_msg void OnTimer(UINT nIDEvent);

	BOOL GetBitmapAndPalette(UINT nIDResource, CBitmap &bitmap, CPalette &pal);

	UINT m_nBitmapID;
	UINT m_nDuration;
	UINT m_nTimerID;
	CBitmap m_bitmap;
	CPalette m_pal;
	CWnd m_wndInvisible;


// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MYSPLASHWND_H__08C608F3_1FB3_11D1_830E_58A47E000000__INCLUDED_)

// MySplashWnd.cpp : implementation file

#include "stdafx.h"
#include "RichEdit.h"
#include "MySplashWnd.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;

// CMySplashWnd

CMySplashWnd::CMySplashWnd(UINT nBitmapID, UINT nDuration /*= 2500*)
	m_nBitmapID = nBitmapID;
	m_nDuration = nDuration;


BOOL CMySplashWnd::Create()
	if( !GetBitmapAndPalette(m_nBitmapID, m_bitmap, m_pal) )
		TRACE1( "Could not load bitmap resource - %d\n", m_nBitmapID );
		return FALSE;

	m_bitmap.GetObject(sizeof(BITMAP), &bm);
	// First create an invisible window
			_T(""), WS_POPUP, 0, 0, 
			bm.bmWidth, bm.bmHeight, NULL, NULL);

	// Create the the splash window with invisible parent as parent
	BOOL bRetVal = CWnd::CreateEx(WS_EX_TOPMOST, 
			_T(""), WS_POPUP, 0, 0, 
			bm.bmWidth, bm.bmHeight, m_wndInvisible.m_hWnd, NULL);

	//Create the timer.
	m_nTimerID = SetTimer(1, m_nDuration, NULL);
	return bRetVal;

BOOL CMySplashWnd::GetBitmapAndPalette(UINT nIDResource, CBitmap &bitmap, CPalette &pal)
	LPCTSTR lpszResourceName = (LPCTSTR)nIDResource;

	HBITMAP hBmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(), 
			lpszResourceName, IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION );

	if( hBmp == NULL ) 
		return FALSE;

	bitmap.Attach( hBmp );

	// Create a logical palette for the bitmap
	BITMAPINFOHEADER &bmInfo = ds.dsBmih;
	bitmap.GetObject( sizeof(ds), &ds );

	int nColors = bmInfo.biClrUsed ? bmInfo.biClrUsed : 1 << bmInfo.biBitCount;

	// Create a halftone palette if colors > 256. 
	CClientDC dc(NULL);			// Desktop DC
	if( nColors > 256 )
		pal.CreateHalftonePalette( &dc );
		// Create the palette

		RGBQUAD *pRGB = new RGBQUAD[nColors];
		CDC memDC;

		memDC.SelectObject( &bitmap );
		::GetDIBColorTable( memDC, 0, nColors, pRGB );

		UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);

		pLP->palVersion = 0x300;
		pLP->palNumEntries = nColors;

		for( int i=0; i < nColors; i++)
			pLP->palPalEntry[i].peRed = pRGB[i].rgbRed;
			pLP->palPalEntry[i].peGreen = pRGB[i].rgbGreen;
			pLP->palPalEntry[i].peBlue = pRGB[i].rgbBlue;
			pLP->palPalEntry[i].peFlags = 0;

		pal.CreatePalette( pLP );

		delete[] pLP;
		delete[] pRGB;

	return TRUE;

void CMySplashWnd::OnPaint() 
	CPaintDC dc(this); // device context for painting
	// Create a memory DC compatible with the paint DC
	CDC memDC;
	memDC.CreateCompatibleDC( &dc );

	CBitmap *pBmpOld = memDC.SelectObject( &m_bitmap );

	// Select and realize the palette
	if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && m_pal.m_hObject != NULL )
		dc.SelectPalette( &m_pal, FALSE );

	// Window is same size as bitmap
	CRect rcWnd;
	GetWindowRect( &rcWnd );
	dc.BitBlt(0, 0, rcWnd.Width(), rcWnd.Height(), &memDC, 0, 0,SRCCOPY);

	// Restore bitmap in memDC
	memDC.SelectObject( pBmpOld );
	// Do not call CWnd::OnPaint() for painting messages

void CMySplashWnd::OnTimer(UINT nIDEvent) 
	if (m_nTimerID == nIDEvent)
		//Destroy the timer and splash window
		delete this;

BOOL CMySplashWnd::PreTranslateMessage(MSG* pMsg) 
	ASSERT(pMsg != NULL);
	if (pMsg->message == WM_KEYDOWN ||
			pMsg->message == WM_SYSKEYDOWN ||
			pMsg->message == WM_LBUTTONDOWN ||
			pMsg->message == WM_RBUTTONDOWN ||
			pMsg->message == WM_MBUTTONDOWN )
		//Destroy the timer and splash window
		delete this;
		return 1;
	return CWnd::PreTranslateMessage(pMsg);

The CMySplashWnd object created with the resource ID of the bitmap that will be shown in the splash screen. You can also provide a second argument for the number milliseconds that the splash screen should be displayed. If you don't provide a second argument to the constructor, it defaults to 2500 milliseconds.

Once the object has been constructed, the window itself has to be created by a call to Create(). This function uses the GetBitmapAndPalette() function to load the bitmap resource and also create a logical palette from the color information in the bitmap. The GetBitmapAndPalette() function has been explained in the section on bitmaps and palettes. If you want to know its working, you can refer to that section.

The Create() function goes on to create an invisible window. It will use this window as a parent window. Since the parent window is not made visible, it wont appear on the taskbar. If you do not use an invisible window and use it as a parent window, then the splash window will show up in the taskbar. Actually there is an easier way to make a topmost window not appear in the taskbar; assign it the WS_EX_TOOLWINDOW style. However, the problem with the WS_EX_TOOLWINDOW style is that it handles the palette differently. It forces any palette realization to the background mode. This, of course, would effect the colors displayed in the splash screen.

The splash window is created with the same widht and height as the bitmap. When creating the window it does not use the WS_VISIBLE style, because the window is centered before it is displayed. The WS_EX_TOPMOST style makes sure that the splash screen does not get covered by any other window. After centering the window and showing it, the Create() function sets a system timer. The timer will be used to destroy the window after the desired number of milliseconds have elapsed.

The OnPaint() function paints the bitmap to the screen after selecting and realizing the logical palette. The OnTimer() function destroys the splash window (actually the parent, which destroys the splash window in turn), the timer and the object itself. The PreTranslateMessage() also destroys the splash window when key down or a mouse down event is received.

Step 2: Create splash screen in CWinApp::InitInstance()

To create the splash screen, allocate a CMySplashWnd object and call the create function. You do not have to delete the object since it deletes itself. You can place this code at the top of the InitInstance() function or if your application uses a CCommandLineInfo object, you can create the splash screen after the call to ParseCommandLine() as shown below. The advantage of using the CCommandLineInfo object is that you can check whether the splash should be displayed at all.
	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;

	if( cmdInfo.m_bShowSplash )
		CMySplashWnd * pSplashWnd = new CMySplashWnd(IDB_SPLASH,2500);


  • Thanks

    Posted by Legacy on 12/04/2001 12:00am

    Originally posted by: Tea

    Thanks a lot..
    your work it's very nice.. and useful..

    Bye Bye


  • Sorry but it does support 256 colors

    Posted by Legacy on 05/28/2001 12:00am

    Originally posted by: Ghost

    You don't have to do all that but I guess you learned a lot writing that code and deserve credit for your hard work and then sharing your work. All you have to do is insert the bitmap but you can't view it or edit it will the visual c++ editor. It will work fine just did mine today.

  • Splash screen

    Posted by Legacy on 03/14/2001 12:00am

    Originally posted by: Jackhamr

    I tried to compile the code in this article and I am getting the following error from the compiler:

    " fatal error C1071: unexpected end of file found in comment"
    This error is coming up trying to compile the MySplashWnd.cpp

    Can anyone tell me what I have to do to get this to work??



  • Cleaner cleanup

    Posted by Legacy on 02/04/2001 12:00am

    Originally posted by: Howard Yoo

    Instead of using 'delete this' to self-destruct the object in OnTimer and PreTranslateMessage, override PostNcDestroy as shown below and send a WM_CLOSE message to the splash windows.  This will let MFC do the proper cleanup required.  I think this is the proper way of self-destructing since PostNcDestroy is the absolute last method (AFAIK) called by the framework before it calls the destructor;

    void YourClass::PostNcDestroy()
    delete this;

    This may solve some of the problems posted earlier.

    Hope this helps.

  • A problem when showing a dialogue

    Posted by Legacy on 12/06/2000 12:00am

    Originally posted by: Andrew Truckle

    I have the splash screen showing for 5 seconds in InitInstance. I then show a dialogue. I get an assertion if the dialogue is still up when the splash screen wants to close down.

    How do I solve?

  • Is there a memory problem here?

    Posted by Legacy on 05/30/2000 12:00am

    Originally posted by: Scott

    I believe that since you are using the new operator, you are allocating memory.  The problem is is that you are not deallocating the memory when the program shuts down.  You may want to add a destructor or delete function to your code.


  • An even easier way

    Posted by Legacy on 12/29/1998 12:00am

    Originally posted by: Mike Haney

    Actually, you don't have to change anything. The Splash Screen component DOES support 256 color bitmaps. It will generate a 16 color bitmap, but you can write over that file with a 256 color bitmap and it will work fine. This works in VC5 and up. Haven't tested it in earlier versions.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date