home *** CD-ROM | disk | FTP | other *** search
- // 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-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- //
-
- #include "stdafx.h"
- #include "mdi.h"
- #include "bounce.h"
-
- #define ABS(x) ((x) < 0? -(x) : (x) > 0? (x) : 0)
-
-
- /////////////////////////////////////////////////////////////////////////////
- // CBounceWnd
-
- BEGIN_MESSAGE_MAP(CBounceWnd, CMDIChildWnd)
- //{{AFX_MSG_MAP(CBounceWnd)
- ON_WM_CREATE()
- ON_WM_SIZE()
- ON_WM_TIMER()
- ON_COMMAND(IDM_BLACK, OnColor)
- ON_COMMAND(IDM_CUSTOM, OnCustomColor)
- ON_COMMAND(IDM_RED, OnColor)
- ON_COMMAND(IDM_GREEN, OnColor)
- ON_COMMAND(IDM_BLUE, OnColor)
- ON_COMMAND(IDM_WHITE, OnColor)
- ON_UPDATE_COMMAND_UI(IDM_SLOW, OnUpdateSlow)
- ON_COMMAND(IDM_SLOW, OnSlow)
- ON_UPDATE_COMMAND_UI(IDM_RED, OnUpdateColor)
- ON_UPDATE_COMMAND_UI(IDM_WHITE, OnUpdateColor)
- ON_UPDATE_COMMAND_UI(IDM_GREEN, OnUpdateColor)
- ON_COMMAND(IDM_FAST, OnFast)
- ON_UPDATE_COMMAND_UI(IDM_FAST, OnUpdateFast)
- ON_UPDATE_COMMAND_UI(IDM_CUSTOM, OnUpdateColor)
- ON_UPDATE_COMMAND_UI(IDM_BLUE, OnUpdateColor)
- ON_UPDATE_COMMAND_UI(IDM_BLACK, OnUpdateColor)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- CMenu NEAR CBounceWnd::menu; // menu for all BOUNCE windows
-
- /////////////////////////////////////////////////////////////////////////////
- // CBounceWnd creation
-
- BOOL CBounceWnd::Create(LPCTSTR szTitle, LONG style /* = 0 */,
- const RECT& rect /* = rectDefault */,
- CMDIFrameWnd* parent /* = NULL */)
- {
- // Setup the shared menu
- if (menu.m_hMenu == NULL)
- menu.LoadMenu(IDR_BOUNCE);
- m_hMenuShared = menu.m_hMenu;
-
- // Register a custom WndClass and create a window.
- // This must be done because CBounceWnd has a custom cursor, and
- // no icon.
- LPCTSTR lpszBounceClass =
- AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
- LoadCursor(NULL, IDC_UPARROW),
- (HBRUSH)(COLOR_WINDOW+1),
- NULL);
-
- return CMDIChildWnd::Create(lpszBounceClass, szTitle, style, rect, parent);
- }
-
- CBounceWnd::CBounceWnd()
- {
- m_nIDColor = IDM_BLACK;
- m_clrBall = RGB(0,0,0);
- m_bFastSpeed = FALSE;
- }
-
-
- // Set up the ball parameters and start a timer.
- int CBounceWnd::OnCreate(LPCREATESTRUCT /* p */)
- {
- if (!SetTimer(1, 100 /*start slow*/, NULL))
- {
- MessageBox(_T("Not enough timers available for this window."),
- _T("MDI:Bounce"), MB_ICONEXCLAMATION | MB_OK);
-
- // signal creation failure...
- return -1;
- }
-
- CDC* pDC = GetDC();
- m_ptPixel.x = pDC->GetDeviceCaps(ASPECTX);
- m_ptPixel.y = 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;
- }
-
- // 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()
- {
- m_sizeTotal.cx = (m_sizeRadius.cx + ABS(m_sizeMove.cx)) << 1;
- m_sizeTotal.cy = (m_sizeRadius.cy + ABS(m_sizeMove.cy)) << 1;
-
- if (m_bmBall.m_hObject != NULL)
- m_bmBall.DeleteObject(); // get rid of old bitmap
-
- CClientDC dc(this);
- CDC dcMem;
- dcMem.CreateCompatibleDC(&dc);
-
- m_bmBall.CreateCompatibleBitmap(&dc, m_sizeTotal.cx, m_sizeTotal.cy);
- ASSERT(m_bmBall.m_hObject != NULL);
-
- CBitmap* pOldBitmap = dcMem.SelectObject(&m_bmBall);
-
- // draw a rectangle in the background (window) color
- CRect rect(0, 0, m_sizeTotal.cx, m_sizeTotal.cy);
- 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_sizeMove.cx), ABS(m_sizeMove.cy),
- m_sizeTotal.cx - ABS(m_sizeMove.cx),
- m_sizeTotal.cy - ABS(m_sizeMove.cy));
-
- dcMem.SelectObject(pOldBrush);
- dcMem.SelectObject(pOldBitmap);
- dcMem.DeleteDC();
- }
-
- // The ball's size and displacement change according to the window size.
- void CBounceWnd::OnSize(UINT nType, int cx, int cy)
- {
- LONG lScale;
-
- m_ptCenter.x = cx >> 1;
- m_ptCenter.y = cy >> 1;
- m_ptCenter.x += cx >> 3; // make the ball a little off-center
-
- lScale = min((LONG)cx * m_ptPixel.x,
- (LONG)cy * m_ptPixel.y) >> 4;
- m_sizeRadius.cx = (int)(lScale / m_ptPixel.x);
- m_sizeRadius.cy = (int)(lScale / m_ptPixel.y);
- m_sizeMove.cx = max(1, m_sizeRadius.cy >> 2);
- m_sizeMove.cy = max(1, m_sizeRadius.cy >> 2);
-
- MakeNewBall();
-
- CMDIChildWnd::OnSize(nType, cx, cy);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CBounceWnd commands
-
- void CBounceWnd::OnUpdateColor(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck(pCmdUI->m_nID == m_nIDColor);
- }
-
- void CBounceWnd::OnColor()
- {
- m_nIDColor = LOWORD(GetCurrentMessage()->wParam);
- m_clrBall = colorArray[m_nIDColor - IDM_BLACK];
-
- // Force the client area text to be repainted in the new color
- MakeNewBall();
- Invalidate();
- }
-
- void CBounceWnd::OnCustomColor()
- {
- CColorDialog dlgColor(m_clrBall);
- if (dlgColor.DoModal() == IDOK)
- {
- m_clrBall = dlgColor.GetColor();
- m_nIDColor = IDM_CUSTOM;
- MakeNewBall();
- Invalidate();
- }
- }
-
- // Change the ball's speed
- void CBounceWnd::ChangeSpeed()
- {
- // re-create the timer
- KillTimer(1);
- if (!SetTimer(1, m_bFastSpeed ? 0 : 100, NULL))
- {
- MessageBox(_T("Not enough timers available for this window."),
- _T("MDI:Bounce"), MB_ICONEXCLAMATION | MB_OK);
- DestroyWindow();
- }
- }
-
- // Animate the ball.
- void CBounceWnd::OnTimer(UINT /* wParam */)
- {
- if (m_bmBall.m_hObject == NULL)
- return; // no bitmap for the ball
-
- CRect rcClient;
- GetClientRect(rcClient);
-
- CClientDC dc(this);
- CBitmap* pbmOld = NULL;
-
- CDC dcMem;
- dcMem.CreateCompatibleDC(&dc);
- pbmOld = dcMem.SelectObject(&m_bmBall);
-
- dc.BitBlt(m_ptCenter.x - m_sizeTotal.cx / 2,
- m_ptCenter.y - m_sizeTotal.cy / 2,
- m_sizeTotal.cx, m_sizeTotal.cy,
- &dcMem, 0, 0, SRCCOPY);
-
- m_ptCenter += m_sizeMove;
-
- if ((m_ptCenter.x + m_sizeRadius.cx >= rcClient.right) ||
- (m_ptCenter.x - m_sizeRadius.cx <= 0))
- {
- m_sizeMove.cx = -m_sizeMove.cx;
- }
-
- if ((m_ptCenter.y + m_sizeRadius.cy >= rcClient.bottom) ||
- (m_ptCenter.y - m_sizeRadius.cy <= 0))
- {
- m_sizeMove.cy = -m_sizeMove.cy;
- }
-
- dcMem.SelectObject(pbmOld);
- dcMem.DeleteDC();
- }
-
- void CBounceWnd::OnUpdateSlow(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck(!m_bFastSpeed);
- }
-
- void CBounceWnd::OnSlow()
- {
- m_bFastSpeed = FALSE;
- ChangeSpeed();
- }
-
- void CBounceWnd::OnUpdateFast(CCmdUI* pCmdUI)
- {
- pCmdUI->SetCheck(m_bFastSpeed);
- }
-
- void CBounceWnd::OnFast()
- {
- m_bFastSpeed = TRUE;
- ChangeSpeed();
- }
-