Animated Background Banner

The following code is used to display an Animated Banner using the the CmdiMainClient class. You will need to get a set of sequenced bitmaps to show the animation. In my example you can Right-Click to Start/Stop the animation and Left-Click to display a child window, keeping the background animation alive.

For your convenience, the code can be copied and pasted from your browser or downloaded (.zip format).


#include "stdafx.h"
#include "banner.h"
#include "mainfrm.h"

#include "resource.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMdiMainClient

CMdiMainClient::CMdiMainClient()
	:	m_sizeClient(0, 0)
		
{
	VERIFY (m_bmpBackGround.LoadBitmap(IDB_BCKGRD)); 
	ASSERT (m_bmpBackGround.GetSafeHandle());

	VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP0));
	ASSERT (m_bmpBackGround2.GetSafeHandle());

	BmpLoaded = 1;
	StopRotation = FALSE;
}

CMdiMainClient::~CMdiMainClient()
{
	if(m_bmpBackGround.GetSafeHandle())
		m_bmpBackGround.DeleteObject();

	if(m_bmpBackGround2.GetSafeHandle())
		m_bmpBackGround2.DeleteObject();
}


BEGIN_MESSAGE_MAP(CMdiMainClient, CWnd)
	//{{AFX_MSG_MAP(CMdiMainClient)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	ON_WM_TIMER()
	ON_WM_ERASEBKGND()
	ON_WM_RBUTTONDOWN()
	ON_WM_LBUTTONDOWN()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CMdiMainClient message handlers
BOOL CMdiMainClient::OnEraseBkgnd(CDC* pDC)
{
	// Erase only the area needed
	CRect rect;
	GetClientRect(&rect) ;
   
	SetTimer(0,300,NULL);
                                       
	// Place the bitmap
	BITMAP bm ;
	CDC dcMem ;

	BITMAP bm2 ;
	CDC dcMem2;

     
	VERIFY(m_bmpBackGround.GetObject(sizeof(bm), (LPVOID)&bm));
	dcMem.CreateCompatibleDC(NULL);
	CBitmap* pbmpOld = (CBitmap*)dcMem.SelectObject(&m_bmpBackGround); 
	ASSERT(pbmpOld) ;
	// Display red background
	pDC->StretchBlt(0, 0, rect.right, rect.bottom, &dcMem, 0,
				0, bm.bmWidth, bm.bmHeight,SRCCOPY);

	VERIFY(m_bmpBackGround2.GetObject(sizeof(bm2), (LPVOID)&bm2));
	dcMem2.CreateCompatibleDC(NULL);
	dcMem2.SelectObject(&m_bmpBackGround2);
	// Display picture background
	pDC->StretchBlt(200,100,400, 200, &dcMem2, 0,0, bm2.bmWidth, bm2.bmHeight,
					SRCCOPY);

	// Display Instructions
	pDC->SetBkColor(RGB(255,0,0));
	pDC->SetTextColor(RGB(192,192,192));
	pDC->TextOut(480, 500, "Mouse Right Click to Stop/Start Special Effects");
	pDC->TextOut(480, 515, "Mouse Left-Click to Show Child Window");

	// CleanUp
	dcMem.SelectObject(pbmpOld) ;

	return TRUE;
}      

////////////////////////////////////////////////////////////////////
//
void CMdiMainClient::OnSize(UINT nType, int cx, int cy)
{
    Default() ;                
    // if the app is just starting up, save the window
    // dimensions and get out

    if ((m_sizeClient.cx == 0) && (m_sizeClient.cy==0))
        {
        m_sizeClient.cx = cx;
        m_sizeClient.cy = cy;

        return ;
        }

    // if the size hasn't changed, break and pass to default

    if ((m_sizeClient.cx == cx) && ( m_sizeClient.cy == cy))
    { 
        return ;
    }

    // window size has changed so save new dimensions and force
    // entire background to redraw, including icon backgrounds

    m_sizeClient.cx = cx;
    m_sizeClient.cy = cy;
             
    RedrawWindow(NULL, NULL,
        RDW_INVALIDATE|RDW_ERASE|RDW_ERASENOW|RDW_ALLCHILDREN);    
            
    return ;                
}

void CMdiMainClient::OnTimer(UINT nIDEvent) 
{
	DisplayNextLogoFrame();
	CWnd::OnTimer(nIDEvent);
}


void CMdiMainClient::DisplayNextLogoFrame() 
{
		CRect rect;
		GetClientRect(&rect) ;
    
		BITMAP bm2 ;
		CDC dcMem2;

		CDC *pDC = GetDC();

		if (!StopRotation)
		{
			// Select next logo frame to be displayed
			switch (BmpLoaded)
			{
		case 1:	if(m_bmpBackGround2.GetSafeHandle())
					m_bmpBackGround2.DeleteObject();
			VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP1));
			ASSERT (m_bmpBackGround2.GetSafeHandle());
			break;
			case 2:	if(m_bmpBackGround2.GetSafeHandle())
					m_bmpBackGround2.DeleteObject();
			VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP2));
			ASSERT (m_bmpBackGround2.GetSafeHandle());
			break;
			case 3:	if(m_bmpBackGround2.GetSafeHandle())
					m_bmpBackGround2.DeleteObject();
			VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP3));
			ASSERT (m_bmpBackGround2.GetSafeHandle());
			break;
			case 4:	if(m_bmpBackGround2.GetSafeHandle())
					m_bmpBackGround2.DeleteObject();
			VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP4));
			ASSERT (m_bmpBackGround2.GetSafeHandle());
			break;
			case 5:	if(m_bmpBackGround2.GetSafeHandle())
					m_bmpBackGround2.DeleteObject();
			VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP5));
			ASSERT (m_bmpBackGround2.GetSafeHandle());
			break;
			case 6:	if(m_bmpBackGround2.GetSafeHandle())
					m_bmpBackGround2.DeleteObject();
			VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP6));
			ASSERT (m_bmpBackGround2.GetSafeHandle());
			break;
			case 7:	if(m_bmpBackGround2.GetSafeHandle())
					m_bmpBackGround2.DeleteObject();
			VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP7));
			ASSERT (m_bmpBackGround2.GetSafeHandle());
			break;
			case 8:	if(m_bmpBackGround2.GetSafeHandle())
					m_bmpBackGround2.DeleteObject();
			VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP8));
			ASSERT (m_bmpBackGround2.GetSafeHandle());
			break;
			case 9:	if(m_bmpBackGround2.GetSafeHandle())
					m_bmpBackGround2.DeleteObject();
			VERIFY (m_bmpBackGround2.LoadBitmap(IDB_BITMAP9));
			ASSERT (m_bmpBackGround2.GetSafeHandle());
			break;
			}
			// Change Bitmap index
			if (BmpLoaded == 9)
				BmpLoaded = 0;
			else
				BmpLoaded++;
		}
          
	VERIFY(m_bmpBackGround2.GetObject(sizeof(bm2), (LPVOID)&bm2));
	dcMem2.CreateCompatibleDC(NULL);
	dcMem2.SelectObject(&m_bmpBackGround2);
	pDC->StretchBlt(200,100,400, 200, &dcMem2, 0,0, bm2.bmWidth, bm2.bmHeight,
		SRCCOPY);

	ReleaseDC(pDC);
}

void CMdiMainClient::OnRButtonDown(UINT nFlags, CPoint point) 
{
	if (StopRotation)
		StopRotation = FALSE;
	else
		StopRotation = TRUE;

	CWnd::OnRButtonDown(nFlags, point);
}

void CMdiMainClient::OnLButtonDown(UINT nFlags, CPoint point) 
{
	m_Hide_Logo = TRUE;
	KillTimer(0);

	// Display Application
	((CBannerApp*)AfxGetApp())->pDocTemplate->OpenDocumentFile(NULL);

	CWnd::OnLButtonDown(nFlags, point);
}

// MdiMainClient.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CMdiMainClient window

extern BOOL m_Hide_Logo;

class CMdiMainClient : public CWnd
{
// Construction
public:
	CMdiMainClient();

// Attributes
protected:
	CBitmap m_bmpBackGround2;
	CBitmap m_bmpBackGround;

	int BmpLoaded;
public:
	BOOL StopRotation;
	CSize m_sizeClient;

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMdiMainClient)
	//}}AFX_VIRTUAL

// Implementation
public:
	void Display_Blank_Bitmap();
	void DisplayNextLogoFrame();
	virtual ~CMdiMainClient();
	// Generated message map functions
protected:
	//{{AFX_MSG(CMdiMainClient)
		// NOTE - the ClassWizard will add and remove member functions here.
		afx_msg BOOL OnEraseBkgnd(CDC* pDC);
		afx_msg void OnSize(UINT nType, int cx, int cy);
		afx_msg void OnTimer(UINT nIDEvent);
		afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
		afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

Download demo project - 86 KB

Download source - 3 KB



Comments

  • How can i do the same in a OpenGL device context?

    Posted by Legacy on 09/18/2001 12:00am

    Originally posted by: Lorien

    I have done all you tell for paint an image as bg before OpenGL paints window (without erasing it) but the result is a flicker betwen the bg i paint and the OpenGL render scene...

    If you know how can i handle the OpenGL device context (or render one) to use the BitBlt or similar functions, please, let me know by mail (in catalan, english or spanish) at: lorien@postmaster.co.uk

    Thanks.

    Lorien! :p

    Reply
  • Why do people still insist on not using hungarian?

    Posted by Legacy on 02/08/2000 12:00am

    Originally posted by: Nev Delap

    Why do people still insist on not using hungarian to name their variables???

    • Hungarian! Yuck!

      Posted by Nev Delap on 04/21/2012 09:11pm

      Maybe if I went back to C I'd rediscover a need for Hungarian. But now in 2012 I can't believe I ever thought that!

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

Top White Papers and Webcasts

  • At present, the most commonly deployed parallel file system is Lustre, and its adoption is growing across the HPC industry. According to Intersect 360 Research, "Through its leadership and involvement with OpenSFS, Cray advocates for the development of features that drive efficient performance at scale." Moreover, with help from Cray and OpenSFS, Lustre is gaining greater adoption across broader commercial application categories. As data and I/O requirements grow in commercial markets, technology vendors -- …

  • The 2014 State of DevOps Report — based on a survey of 9,200+ people in IT operations, software development and technology management roles in 110 countries — reveals: Companies with high-performing IT organizations are twice as likely to exceed their profitability, market share and productivity goals. IT performance improves with DevOps maturity, and strongly correlates with well-known DevOps practices. Job satisfaction is the No. 1 predictor of performance against organizational …

Most Popular Programming Stories

More for Developers

RSS Feeds

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