File:  [WindowsNT SDKs] / mstools / mfc / samples / mdi / bounce.cpp
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:21:00 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-oct-1992, ntsdk-jun-1992, ntsdk-jul-1993, HEAD
Microsoft Windows NT Build 297 06-28-1992

// bounce.cpp : Defines the class behaviors for the Bounce child window.
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and Microsoft
// QuickHelp documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
//

#include "mdi.h"

static COLORREF clrTextArray[] = { RGB (0,   0, 0), RGB (255, 0,   0),
								   RGB (0, 255, 0), RGB (  0, 0, 255),
								   RGB (255, 255, 255) };

#define ABS(x) ((x) < 0? -(x) : (x) > 0? (x) : 0)


/////////////////////////////////////////////////////////////////////////////
// CBounceWnd

BEGIN_MESSAGE_MAP(CBounceWnd, CMDIChildWnd)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_SIZE()
	ON_WM_TIMER()
	ON_WM_MDIACTIVATE()
	ON_COMMAND(IDM_BLACK, OnColor)
	ON_COMMAND(IDM_RED,   OnColor)
	ON_COMMAND(IDM_GREEN, OnColor)
	ON_COMMAND(IDM_BLUE,  OnColor)
	ON_COMMAND(IDM_WHITE, OnColor)
	ON_COMMAND(IDM_CUSTOM, OnColor)
	ON_COMMAND(IDM_SLOW,  OnSpeed)
	ON_COMMAND(IDM_FAST,  OnSpeed)
END_MESSAGE_MAP()

// Create:
// Register a custom WndClass and create a window.
// This must be done because CBounceWnd has a custom cursor.
// 
BOOL CBounceWnd::Create(LPCSTR szTitle, LONG style /* = 0 */,
	const RECT& rect /* = rectDefault */,
	CMDIFrameWnd* parent /* = NULL */)
{
	const char* pszBounceClass = 
		AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
			LoadCursor(NULL, IDC_UPARROW), 
			(HBRUSH)(COLOR_WINDOW+1),
			NULL);

	return CMDIChildWnd::Create(pszBounceClass, szTitle, style, rect, parent);
}

// Constructor:
// Minimum initialization
//
CBounceWnd::CBounceWnd()
{
	m_pBitmap = NULL;
	m_pMenuCurrent = NULL;
	m_bWindowActive = FALSE;
}

// Destructor:
// Release Windows resources
//
CBounceWnd::~CBounceWnd()
{
	if (m_bWindowActive)
	{
		// Suppress Foundation DestroyMenu done in CMenu destructor 
		// (Windows takes care of menu cleanup for the active window)
		//
		m_pMenuCurrent->Detach();
	}

	delete m_pBitmap;

	if (m_nSpeed != 0)
		KillTimer(1);
}


// OnCreate:
// Set up the ball parameters and start a timer.
//
int CBounceWnd::OnCreate(LPCREATESTRUCT /* p */)
{
	m_nSpeed = IDM_SLOW;
	if (!SetTimer(1, (m_nSpeed==IDM_SLOW? 100 : 0), NULL))
	{
		MessageBox("Not enough timers available for this window.",
				"MDI:Bounce", MB_ICONEXCLAMATION | MB_OK);

		m_nSpeed = 0;

		// signal creation failure...
		return -1;
	}
	else
	{
		m_nColor = IDM_BLACK;
		m_clrBall = clrTextArray[m_nColor - IDM_BLACK];

		CDC* pDC = GetDC();
		m_xPixel = pDC->GetDeviceCaps(ASPECTX);
		m_yPixel = pDC->GetDeviceCaps(ASPECTY);
		ReleaseDC(pDC);

	// Note that we could call MakeNewBall here (which should be called
	// whenever the ball's speed, color or size has been changed), but the
	// OnSize member function is always called after the OnCreate. Since
	// the OnSize member has to call MakeNewBall anyway, we don't here.
	//

	}

	return 0;
}

// OnDestroy:
// Notify app main MDI frame window of destruction so it may
// do some cleanup.  Note: this uses a custom message -- see
// mdi.h and mdi.cpp for the custom message handler
//
void CBounceWnd::OnDestroy()
{
	m_pMDIFrameWnd->SendMessage(WM_CHILDDESTROY, (UINT)m_hWnd, 0);
}

// MakeNewBall:
// Whenever a parameter changes which would affect the speed or appearance
// of the ball, call this to regenerate the ball bitmap.
//
void CBounceWnd::MakeNewBall()
{
	if (m_pBitmap != NULL)
	{
		// Reclaim Windows resources associated with the ball bitmap
		// before redrawing

		m_pBitmap->DeleteObject();
	}
	else
	{
		m_pBitmap = new CBitmap;
	}

	m_cxTotal = (m_cxRadius + ABS(m_cxMove)) << 1;
	m_cyTotal = (m_cyRadius + ABS(m_cyMove)) << 1;

	CDC dcMem;
	CDC* pDC = GetDC();
	
	dcMem.CreateCompatibleDC(pDC);

	m_pBitmap->CreateCompatibleBitmap(pDC, m_cxTotal, m_cyTotal);

	ASSERT(m_pBitmap->m_hObject != NULL);

	ReleaseDC(pDC);


	CBitmap* pOldBitmap = dcMem.SelectObject(m_pBitmap);

	// draw a rectangle in the background (window) color
	CRect rect(0, 0, m_cxTotal, m_cyTotal);
	CBrush brBackground(::GetSysColor(COLOR_WINDOW));
	dcMem.FillRect(rect, &brBackground);

	CBrush brCross(HS_DIAGCROSS, 0L);
	CBrush* pOldBrush = dcMem.SelectObject(&brCross);

	dcMem.SetBkColor(m_clrBall);
	dcMem.Ellipse(ABS(m_cxMove), ABS(m_cyMove),
					m_cxTotal - ABS(m_cxMove), m_cyTotal - ABS(m_cyMove));

	dcMem.SelectObject(pOldBrush);
	dcMem.SelectObject(pOldBitmap);
	dcMem.DeleteDC();
}

// OnSize:
// The ball's size and displacement change according to the window size.
//
void CBounceWnd::OnSize(UINT nType, int cx, int cy)
{
	LONG lScale;

	m_xCenter = (m_cxClient = cx) >> 1;
	m_yCenter = (m_cyClient = cy) >> 1;
	m_xCenter += m_cxClient >> 3; // make the ball a little off-center

	lScale = min((LONG)m_cxClient * m_xPixel,
		(LONG)m_cyClient * m_yPixel) >> 4;
	m_cxRadius = (short)(lScale / m_xPixel);
	m_cyRadius = (short)(lScale / m_yPixel);
	m_cxMove = max(1, m_cyRadius >> 2);
	m_cyMove = max(1, m_cyRadius >> 2);

	MakeNewBall();

	CMDIChildWnd::OnSize(nType, cx, cy);
}

// OnColor:
// The ball's color needs to be changed.  Checkmark the right color on the
// menu.
//
void CBounceWnd::OnColor()
{
	CMenu* pMenu = m_pMDIFrameWnd->GetMenu();
	pMenu->CheckMenuItem(m_nColor, MF_UNCHECKED);

	m_nColor = GetCurrentMessage()->wParam;
	pMenu->CheckMenuItem(m_nColor, MF_CHECKED);

	if (m_nColor != IDM_CUSTOM)
		m_clrBall = clrTextArray[m_nColor - IDM_BLACK];
	else
	{
		CColorDialog dlgColor(m_clrBall);
		if (dlgColor.DoModal() == IDOK)
			m_clrBall = dlgColor.GetColor();
	}

	MakeNewBall();

	Invalidate();
}

// OnSpeed:
// The ball's speed needs to be changed.  Checkmark the menus, kill the
// current timer and start a new one at the new speed.
//
void CBounceWnd::OnSpeed()
{
	CMenu* pMenu = m_pMDIFrameWnd->GetMenu();
	pMenu->CheckMenuItem(m_nSpeed, MF_UNCHECKED);

	m_nSpeed = GetCurrentMessage()->wParam;
	pMenu->CheckMenuItem(m_nSpeed, MF_CHECKED);

	KillTimer(1);
	if (!SetTimer(1, (m_nSpeed==IDM_SLOW? 100 : 0), NULL))
	{
		MessageBox("Not enough timers available for this window.",
				"MDI:Bounce", MB_ICONEXCLAMATION | MB_OK);

		m_nSpeed = 0;

		DestroyWindow();
	}
}

// OnTimer:
// Animate the ball.
//
void CBounceWnd::OnTimer(UINT /* wParam */)
{
	if (m_pBitmap != NULL)
	{
		CDC dcMem;
		CDC* pdcScreen = NULL;
		CBitmap* pOldMap = NULL;

		pdcScreen = GetDC();    

		dcMem.CreateCompatibleDC(pdcScreen);

		ASSERT(m_pBitmap->m_hObject != NULL);

		pOldMap = dcMem.SelectObject(m_pBitmap);
	
		pdcScreen->BitBlt(m_xCenter - m_cxTotal / 2,
					m_yCenter - m_cyTotal / 2, m_cxTotal, m_cyTotal,
					&dcMem, 0, 0, SRCCOPY);
	
		ReleaseDC(pdcScreen);
	
		m_xCenter += m_cxMove;
		m_yCenter += m_cyMove;
	
		if ((m_xCenter + m_cxRadius >= m_cxClient) || 
			(m_xCenter - m_cxRadius <= 0))
		{
			m_cxMove = -m_cxMove;
		}
	
		if ((m_yCenter + m_cyRadius >= m_cyClient) || 
			(m_yCenter - m_cyRadius <= 0))
		{
			m_cyMove = -m_cyMove;
		}
	
		dcMem.SelectObject(pOldMap);
		dcMem.DeleteDC();
	}
}

// OnMDIActivate:
// The current window is being activated or deactivated.  
// Change MDI frame window menu as appropriate.
//

void CBounceWnd::OnMDIActivate(BOOL bActivate, CWnd* /*pActive*/, 
							   CWnd* /*pDeActive*/)
{

	CMDIFrameWnd* pFrame = m_pMDIFrameWnd;
	CMenu* pWinPopupMenu = NULL;
	CMenu* pMenu = NULL;

	m_bWindowActive = bActivate;

	if (bActivate)
	{
		pMenu = new CMenu;
		pMenu->LoadMenu("MdiMenuBounce");
		pWinPopupMenu = pMenu->GetSubMenu(BOUNCE_MENU_POS);

		CMenu* pLastMenu = pFrame->MDISetMenu(pMenu, pWinPopupMenu);
		pLastMenu->DestroyMenu();

		pMenu->CheckMenuItem(m_nColor, bActivate ? MF_CHECKED : MF_UNCHECKED);
		pMenu->CheckMenuItem(m_nSpeed, bActivate ? MF_CHECKED : MF_UNCHECKED);

		delete m_pMenuCurrent;
		m_pMenuCurrent = pMenu;

	}
	else
	{
		pMenu = new CMenu;
		pMenu->LoadMenu("MdiMenuInit");
		pWinPopupMenu = pMenu->GetSubMenu(INIT_MENU_POS);

		CMenu* pLastMenu = pFrame->MDISetMenu(pMenu, pWinPopupMenu);
		pLastMenu->DestroyMenu();

		delete m_pMenuCurrent;
		m_pMenuCurrent = pMenu;
	}

	pFrame->DrawMenuBar();
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.