home *** CD-ROM | disk | FTP | other *** search
/ Troubleshooting Netware Systems / CSTRIAL0196.BIN / attach / msj / v10n03 / bocole.exe / BOUNCE.CPP next >
C/C++ Source or Header  |  1995-03-01  |  7KB  |  270 lines

  1. // bounce.cpp : Defines the class behaviors for the Bounce child window.
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and Microsoft
  9. // WinHelp documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12. //
  13.  
  14. #include "stdafx.h"
  15. #include "mdi.h"
  16. #include "bounce.h"
  17.  
  18. #define ABS(x) ((x) < 0? -(x) : (x) > 0? (x) : 0)
  19.  
  20.  
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CBounceWnd
  23.  
  24. BEGIN_MESSAGE_MAP(CBounceWnd, CMDIChildWnd)
  25.     //{{AFX_MSG_MAP(CBounceWnd)
  26.     ON_WM_CREATE()
  27.     ON_WM_SIZE()
  28.     ON_WM_TIMER()
  29.     ON_COMMAND(IDM_BLACK, OnColor)
  30.     ON_COMMAND(IDM_CUSTOM, OnCustomColor)
  31.     ON_COMMAND(IDM_RED, OnColor)
  32.     ON_COMMAND(IDM_GREEN, OnColor)
  33.     ON_COMMAND(IDM_BLUE, OnColor)
  34.     ON_COMMAND(IDM_WHITE, OnColor)
  35.     ON_UPDATE_COMMAND_UI(IDM_SLOW, OnUpdateSlow)
  36.     ON_COMMAND(IDM_SLOW, OnSlow)
  37.     ON_UPDATE_COMMAND_UI(IDM_RED, OnUpdateColor)
  38.     ON_UPDATE_COMMAND_UI(IDM_WHITE, OnUpdateColor)
  39.     ON_UPDATE_COMMAND_UI(IDM_GREEN, OnUpdateColor)
  40.     ON_COMMAND(IDM_FAST, OnFast)
  41.     ON_UPDATE_COMMAND_UI(IDM_FAST, OnUpdateFast)
  42.     ON_UPDATE_COMMAND_UI(IDM_CUSTOM, OnUpdateColor)
  43.     ON_UPDATE_COMMAND_UI(IDM_BLUE, OnUpdateColor)
  44.     ON_UPDATE_COMMAND_UI(IDM_BLACK, OnUpdateColor)
  45.     //}}AFX_MSG_MAP
  46. END_MESSAGE_MAP()
  47.  
  48. CMenu NEAR CBounceWnd::menu;        // menu for all BOUNCE windows
  49.  
  50. /////////////////////////////////////////////////////////////////////////////
  51. // CBounceWnd creation
  52.  
  53. BOOL CBounceWnd::Create(LPCSTR szTitle, LONG style /* = 0 */,
  54.     const RECT& rect /* = rectDefault */,
  55.     CMDIFrameWnd* parent /* = NULL */)
  56. {
  57.     // Setup the shared menu
  58.     if (menu.m_hMenu == NULL)
  59.         menu.LoadMenu(IDR_BOUNCE);
  60.     m_hMenuShared = menu.m_hMenu;
  61.  
  62.     // Register a custom WndClass and create a window.
  63.     // This must be done because CBounceWnd has a custom cursor, and
  64.     //  no icon.
  65.     const char* pszBounceClass =
  66.         AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
  67.             LoadCursor(NULL, IDC_UPARROW),
  68.             (HBRUSH)(COLOR_WINDOW+1),
  69.             NULL);
  70.  
  71.     return CMDIChildWnd::Create(pszBounceClass, szTitle, style, rect, parent);
  72. }
  73.  
  74. CBounceWnd::CBounceWnd()
  75. {
  76.     m_nIDColor = IDM_BLACK;
  77.     m_clrBall = RGB(0,0,0);
  78.     m_bFastSpeed = FALSE;
  79. }
  80.  
  81.  
  82. // Set up the ball parameters and start a timer.
  83. int CBounceWnd::OnCreate(LPCREATESTRUCT /* p */)
  84. {
  85.     if (!SetTimer(1, 100 /*start slow*/, NULL))
  86.     {
  87.         MessageBox("Not enough timers available for this window.",
  88.                 "MDI:Bounce", MB_ICONEXCLAMATION | MB_OK);
  89.  
  90.         // signal creation failure...
  91.         return -1;
  92.     }
  93.  
  94.     CDC* pDC = GetDC();
  95.     m_ptPixel.x = pDC->GetDeviceCaps(ASPECTX);
  96.     m_ptPixel.y = pDC->GetDeviceCaps(ASPECTY);
  97.     ReleaseDC(pDC);
  98.  
  99.     // Note that we could call MakeNewBall here (which should be called
  100.     // whenever the ball's speed, color or size has been changed), but the
  101.     // OnSize member function is always called after the OnCreate. Since
  102.     // the OnSize member has to call MakeNewBall anyway, we don't here.
  103.  
  104.     return 0;
  105. }
  106.  
  107. // MakeNewBall:
  108. // Whenever a parameter changes which would affect the speed or appearance
  109. // of the ball, call this to regenerate the ball bitmap.
  110. //
  111. void CBounceWnd::MakeNewBall()
  112. {
  113.     m_sizeTotal.cx = (m_sizeRadius.cx + ABS(m_sizeMove.cx)) << 1;
  114.     m_sizeTotal.cy = (m_sizeRadius.cy + ABS(m_sizeMove.cy)) << 1;
  115.  
  116.     if (m_bmBall.m_hObject != NULL)
  117.         m_bmBall.DeleteObject();        // get rid of old bitmap
  118.  
  119.     CClientDC dc(this);
  120.     CDC dcMem;
  121.     dcMem.CreateCompatibleDC(&dc);
  122.  
  123.     m_bmBall.CreateCompatibleBitmap(&dc, m_sizeTotal.cx, m_sizeTotal.cy);
  124.     ASSERT(m_bmBall.m_hObject != NULL);
  125.  
  126.     CBitmap* pOldBitmap = dcMem.SelectObject(&m_bmBall);
  127.  
  128.     // draw a rectangle in the background (window) color
  129.     CRect rect(0, 0, m_sizeTotal.cx, m_sizeTotal.cy);
  130.     CBrush brBackground(::GetSysColor(COLOR_WINDOW));
  131.     dcMem.FillRect(rect, &brBackground);
  132.  
  133.     CBrush brCross(HS_DIAGCROSS, 0L);
  134.     CBrush* pOldBrush = dcMem.SelectObject(&brCross);
  135.  
  136.     dcMem.SetBkColor(m_clrBall);
  137.     dcMem.Ellipse(ABS(m_sizeMove.cx), ABS(m_sizeMove.cy),
  138.         m_sizeTotal.cx - ABS(m_sizeMove.cx),
  139.         m_sizeTotal.cy - ABS(m_sizeMove.cy));
  140.  
  141.     dcMem.SelectObject(pOldBrush);
  142.     dcMem.SelectObject(pOldBitmap);
  143.     dcMem.DeleteDC();
  144. }
  145.  
  146. // The ball's size and displacement change according to the window size.
  147. void CBounceWnd::OnSize(UINT nType, int cx, int cy)
  148. {
  149.     LONG lScale;
  150.  
  151.     m_ptCenter.x = cx >> 1;
  152.     m_ptCenter.y = cy >> 1;
  153.     m_ptCenter.x += cx >> 3; // make the ball a little off-center
  154.  
  155.     lScale = min((LONG)cx * m_ptPixel.x,
  156.         (LONG)cy * m_ptPixel.y) >> 4;
  157.     m_sizeRadius.cx = (int)(lScale / m_ptPixel.x);
  158.     m_sizeRadius.cy = (int)(lScale / m_ptPixel.y);
  159.     m_sizeMove.cx = max(1, m_sizeRadius.cy >> 2);
  160.     m_sizeMove.cy = max(1, m_sizeRadius.cy >> 2);
  161.  
  162.     MakeNewBall();
  163.  
  164.     CMDIChildWnd::OnSize(nType, cx, cy);
  165. }
  166.  
  167. /////////////////////////////////////////////////////////////////////////////
  168. // CBounceWnd commands
  169.  
  170. void CBounceWnd::OnUpdateColor(CCmdUI* pCmdUI)
  171. {
  172.     pCmdUI->SetCheck(pCmdUI->m_nID == m_nIDColor);
  173. }
  174.  
  175. void CBounceWnd::OnColor()
  176. {
  177.     m_nIDColor = LOWORD(GetCurrentMessage()->wParam);
  178.     m_clrBall = colorArray[m_nIDColor - IDM_BLACK];
  179.  
  180.     // Force the client area text to be repainted in the new color
  181.     MakeNewBall();
  182.     Invalidate();
  183. }
  184.  
  185. void CBounceWnd::OnCustomColor()
  186. {
  187.     CColorDialog dlgColor(m_clrBall);
  188.     if (dlgColor.DoModal() == IDOK)
  189.     {
  190.         m_clrBall = dlgColor.GetColor();
  191.         m_nIDColor = IDM_CUSTOM;
  192.         MakeNewBall();
  193.         Invalidate();
  194.     }
  195. }
  196.  
  197. // Change the ball's speed
  198. void CBounceWnd::ChangeSpeed()
  199. {
  200.     // re-create the timer
  201.     KillTimer(1);
  202.     if (!SetTimer(1, m_bFastSpeed ? 0 : 100, NULL))
  203.     {
  204.         MessageBox("Not enough timers available for this window.",
  205.                 "MDI:Bounce", MB_ICONEXCLAMATION | MB_OK);
  206.         DestroyWindow();
  207.     }
  208. }
  209.  
  210. // Animate the ball.
  211. void CBounceWnd::OnTimer(UINT /* wParam */)
  212. {
  213.     if (m_bmBall.m_hObject == NULL)
  214.         return;     // no bitmap for the ball
  215.  
  216.     CRect rcClient;
  217.     GetClientRect(rcClient);
  218.  
  219.     CClientDC dc(this);
  220.     CBitmap* pbmOld = NULL;
  221.  
  222.     CDC dcMem;
  223.     dcMem.CreateCompatibleDC(&dc);
  224.     pbmOld = dcMem.SelectObject(&m_bmBall);
  225.  
  226.     dc.BitBlt(m_ptCenter.x - m_sizeTotal.cx / 2,
  227.             m_ptCenter.y - m_sizeTotal.cy / 2,
  228.             m_sizeTotal.cx, m_sizeTotal.cy,
  229.             &dcMem, 0, 0, SRCCOPY);
  230.  
  231.     m_ptCenter += m_sizeMove;
  232.  
  233.     if ((m_ptCenter.x + m_sizeRadius.cx >= rcClient.right) ||
  234.         (m_ptCenter.x - m_sizeRadius.cx <= 0))
  235.     {
  236.         m_sizeMove.cx = -m_sizeMove.cx;
  237.     }
  238.  
  239.     if ((m_ptCenter.y + m_sizeRadius.cy >= rcClient.bottom) ||
  240.         (m_ptCenter.y - m_sizeRadius.cy <= 0))
  241.     {
  242.         m_sizeMove.cy = -m_sizeMove.cy;
  243.     }
  244.  
  245.     dcMem.SelectObject(pbmOld);
  246.     dcMem.DeleteDC();
  247. }
  248.  
  249. void CBounceWnd::OnUpdateSlow(CCmdUI* pCmdUI)
  250. {
  251.     pCmdUI->SetCheck(!m_bFastSpeed);
  252. }
  253.  
  254. void CBounceWnd::OnSlow()
  255. {
  256.     m_bFastSpeed = FALSE;
  257.     ChangeSpeed();
  258. }
  259.  
  260. void CBounceWnd::OnUpdateFast(CCmdUI* pCmdUI)
  261. {
  262.     pCmdUI->SetCheck(m_bFastSpeed);
  263. }
  264.  
  265. void CBounceWnd::OnFast()
  266. {
  267.     m_bFastSpeed = TRUE;
  268.     ChangeSpeed();
  269. }
  270.