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
public:
    CMySplashWnd(UINT nBitmapID, UINT nDuration = 2500);

// Attributes
public:
    BOOL Create();

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMySplashWnd)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	//}}AFX_VIRTUAL

// Implementation
public:

	// Generated message map functions
protected:
	//{{AFX_MSG(CMySplashWnd)
	afx_msg void OnPaint();
	afx_msg void OnTimer(UINT nIDEvent);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()

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

protected:
	UINT m_nBitmapID;
	UINT m_nDuration;
	UINT m_nTimerID;
	CBitmap m_bitmap;
	CPalette m_pal;
	CWnd m_wndInvisible;
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// 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__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMySplashWnd

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

BEGIN_MESSAGE_MAP(CMySplashWnd, CWnd)
	//{{AFX_MSG_MAP(CMySplashWnd)
	ON_WM_PAINT()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()



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


	BITMAP bm;
	m_bitmap.GetObject(sizeof(BITMAP), &bm);
	
	// First create an invisible window
	m_wndInvisible.CreateEx(WS_EX_TOPMOST, 
			AfxRegisterWndClass(CS_CLASSDC), 
			_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, 
			AfxRegisterWndClass(CS_CLASSDC), 
			_T(""), WS_POPUP, 0, 0, 
			bm.bmWidth, bm.bmHeight, m_wndInvisible.m_hWnd, NULL);

	CenterWindow();
	ShowWindow(SW_SHOW);
	UpdateWindow();
	
	//Create the timer.
	m_nTimerID = SetTimer(1, m_nDuration, NULL);
	ASSERT(m_nTimerID);
	
	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
	DIBSECTION ds;
	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 );
	else
	{
		// Create the palette

		RGBQUAD *pRGB = new RGBQUAD[nColors];
		CDC memDC;
		memDC.CreateCompatibleDC(&dc);

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

		UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
		LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];

		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 );
		dc.RealizePalette();
	}


	// 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
		KillTimer(m_nTimerID);
		m_wndInvisible.DestroyWindow(); 	
		delete this;
		return;
	}	 
	
	CWnd::OnTimer(nIDEvent);
}

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
		KillTimer(m_nTimerID);
		m_wndInvisible.DestroyWindow(); 	
		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;
	ParseCommandLine(cmdInfo);


	if( cmdInfo.m_bShowSplash )
	{
		CMySplashWnd * pSplashWnd = new CMySplashWnd(IDB_SPLASH,2500);
		pSplashWnd->Create();
	}



Comments

  • Nike Air Max 1 FB press, have on the agenda c trick a eager color character, the brand-new shoes

    Posted by Geozyoceada on 04/25/2013 11:45am

    In the summer in a tumbler interior the cool sprite seems to be a good creme de la creme, but if the sprite "feet"? Resolution also fork out you a trip, get a invigorating! This summer, Nike and Sprite [url=http://fossilsdirect.co.uk/glossarey.cfm]nike huarache free[/url] and his sneakers to a graduate of exemplary snow spread of callow, unsullied and dejected color schematic in the classic Nike Feeling Max 1 shoes reveal a like a breath of fresh air cool scent.[url=http://fossilsdirect.co.uk/glossarey.cfm]nike huarache[/url] Summer is the yet to hand-pick a clean shoe, shoes should be a creditable choice. Qualifying series Nike Quality Max HomeTurf metropolis recently lastly comes up, this series in the first-rate Freshen Max shoes to London, Paris and Milan the three paid tribute to the iconic metropolis of Europe, combined with the characteristics of the three cities, Like Max 1 HYP,Tell Max 90 HYP,Show Max 1 and shoes such as Style Max 95, combined [url=http://northernroofing.co.uk/roofins.cfm]nike free[/url] with the Hyperfuse, as well as a variation of materials, such as suede, Whether you after practicable or retro-everything.

    Reply
  • You demand some tomato basil and mozzarella. In behalf of indoor turn to account, these slippers are as liven up and manueverable as sneakers.

    Posted by Soaceddew on 04/20/2013 12:00am

    Has just released some mod color Subject to Inneva Woven shoes, Nike recently with another technique to lure shoes with diverse styling to all [url=http://markwarren.org.uk/property-waet.cfm]nike air max 90[/url] eyes. This brings steadfast printing Unfastened Inneva Woven is a Fair-skinned Marker of works in the series, represents shoes Italian made the assurance. Latest Liberated Inneva Woven swart and bawdy are available in two color schemes, to hand-knit Woven vamp in addition to infiltrated Italy's [url=http://fossilsdirect.co.uk/glossarey.cfm]nike huarache free[/url] finest crafts, in the meantime gives athletes terminate to the foot of comfort, the most consequential affair is the outclass of Unused 5 configuration, barefoot be aware it will give birth to cannot be ignored. Nike Free Inneva Woven SP Oyster-white Id Pack on Parade 16 at outlets around the [url=http://turbo-vac.co.uk/components_13.cfm]nike free womens[/url] trade name on the shelves, and on trade in narrow bearing, interested friends should produce results close publicity to Nike announced the news.

    Reply
  • 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

    Tea

    Reply
  • 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.
    Ghost

    Reply
  • 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??

    thanks

    Jackhamr


    Reply
  • 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.

    Reply
  • 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?

    Reply
  • 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.
    
    

    Scott

    Reply
  • 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.

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

Top White Papers and Webcasts

  • The explosion in mobile devices and applications has generated a great deal of interest in APIs. Today's businesses are under increased pressure to make it easy to build apps, supply tools to help developers work more quickly, and deploy operational analytics so they can track users, developers, application performance, and more. Apigee Edge provides comprehensive API delivery tools and both operational and business-level analytics in an integrated platform. It is available as on-premise software or through …

  • Live Event Date: September 10, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild". This loop of continuous delivery and continuous feedback is …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds