|
|
1.1 ! root 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: // QuickHelp documentation provided with the library. ! 10: // See these sources for detailed information regarding the ! 11: // Microsoft Foundation Classes product. ! 12: // ! 13: ! 14: #include "mdi.h" ! 15: ! 16: static COLORREF clrTextArray[] = { RGB (0, 0, 0), RGB (255, 0, 0), ! 17: RGB (0, 255, 0), RGB ( 0, 0, 255), ! 18: RGB (255, 255, 255) }; ! 19: ! 20: #define ABS(x) ((x) < 0? -(x) : (x) > 0? (x) : 0) ! 21: ! 22: ! 23: ///////////////////////////////////////////////////////////////////////////// ! 24: // CBounceWnd ! 25: ! 26: BEGIN_MESSAGE_MAP(CBounceWnd, CMDIChildWnd) ! 27: ON_WM_CREATE() ! 28: ON_WM_DESTROY() ! 29: ON_WM_SIZE() ! 30: ON_WM_TIMER() ! 31: ON_WM_MDIACTIVATE() ! 32: ON_COMMAND(IDM_BLACK, OnColor) ! 33: ON_COMMAND(IDM_RED, OnColor) ! 34: ON_COMMAND(IDM_GREEN, OnColor) ! 35: ON_COMMAND(IDM_BLUE, OnColor) ! 36: ON_COMMAND(IDM_WHITE, OnColor) ! 37: ON_COMMAND(IDM_CUSTOM, OnColor) ! 38: ON_COMMAND(IDM_SLOW, OnSpeed) ! 39: ON_COMMAND(IDM_FAST, OnSpeed) ! 40: END_MESSAGE_MAP() ! 41: ! 42: // Create: ! 43: // Register a custom WndClass and create a window. ! 44: // This must be done because CBounceWnd has a custom cursor. ! 45: // ! 46: BOOL CBounceWnd::Create(LPCSTR szTitle, LONG style /* = 0 */, ! 47: const RECT& rect /* = rectDefault */, ! 48: CMDIFrameWnd* parent /* = NULL */) ! 49: { ! 50: const char* pszBounceClass = ! 51: AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, ! 52: LoadCursor(NULL, IDC_UPARROW), ! 53: (HBRUSH)(COLOR_WINDOW+1), ! 54: NULL); ! 55: ! 56: return CMDIChildWnd::Create(pszBounceClass, szTitle, style, rect, parent); ! 57: } ! 58: ! 59: // Constructor: ! 60: // Minimum initialization ! 61: // ! 62: CBounceWnd::CBounceWnd() ! 63: { ! 64: m_pBitmap = NULL; ! 65: m_pMenuCurrent = NULL; ! 66: m_bWindowActive = FALSE; ! 67: } ! 68: ! 69: // Destructor: ! 70: // Release Windows resources ! 71: // ! 72: CBounceWnd::~CBounceWnd() ! 73: { ! 74: if (m_bWindowActive) ! 75: { ! 76: // Suppress Foundation DestroyMenu done in CMenu destructor ! 77: // (Windows takes care of menu cleanup for the active window) ! 78: // ! 79: m_pMenuCurrent->Detach(); ! 80: } ! 81: ! 82: delete m_pBitmap; ! 83: ! 84: if (m_nSpeed != 0) ! 85: KillTimer(1); ! 86: } ! 87: ! 88: ! 89: // OnCreate: ! 90: // Set up the ball parameters and start a timer. ! 91: // ! 92: int CBounceWnd::OnCreate(LPCREATESTRUCT /* p */) ! 93: { ! 94: m_nSpeed = IDM_SLOW; ! 95: if (!SetTimer(1, (m_nSpeed==IDM_SLOW? 100 : 0), NULL)) ! 96: { ! 97: MessageBox("Not enough timers available for this window.", ! 98: "MDI:Bounce", MB_ICONEXCLAMATION | MB_OK); ! 99: ! 100: m_nSpeed = 0; ! 101: ! 102: // signal creation failure... ! 103: return -1; ! 104: } ! 105: else ! 106: { ! 107: m_nColor = IDM_BLACK; ! 108: m_clrBall = clrTextArray[m_nColor - IDM_BLACK]; ! 109: ! 110: CDC* pDC = GetDC(); ! 111: m_xPixel = pDC->GetDeviceCaps(ASPECTX); ! 112: m_yPixel = pDC->GetDeviceCaps(ASPECTY); ! 113: ReleaseDC(pDC); ! 114: ! 115: // Note that we could call MakeNewBall here (which should be called ! 116: // whenever the ball's speed, color or size has been changed), but the ! 117: // OnSize member function is always called after the OnCreate. Since ! 118: // the OnSize member has to call MakeNewBall anyway, we don't here. ! 119: // ! 120: ! 121: } ! 122: ! 123: return 0; ! 124: } ! 125: ! 126: // OnDestroy: ! 127: // Notify app main MDI frame window of destruction so it may ! 128: // do some cleanup. Note: this uses a custom message -- see ! 129: // mdi.h and mdi.cpp for the custom message handler ! 130: // ! 131: void CBounceWnd::OnDestroy() ! 132: { ! 133: m_pMDIFrameWnd->SendMessage(WM_CHILDDESTROY, (UINT)m_hWnd, 0); ! 134: } ! 135: ! 136: // MakeNewBall: ! 137: // Whenever a parameter changes which would affect the speed or appearance ! 138: // of the ball, call this to regenerate the ball bitmap. ! 139: // ! 140: void CBounceWnd::MakeNewBall() ! 141: { ! 142: if (m_pBitmap != NULL) ! 143: { ! 144: // Reclaim Windows resources associated with the ball bitmap ! 145: // before redrawing ! 146: ! 147: m_pBitmap->DeleteObject(); ! 148: } ! 149: else ! 150: { ! 151: m_pBitmap = new CBitmap; ! 152: } ! 153: ! 154: m_cxTotal = (m_cxRadius + ABS(m_cxMove)) << 1; ! 155: m_cyTotal = (m_cyRadius + ABS(m_cyMove)) << 1; ! 156: ! 157: CDC dcMem; ! 158: CDC* pDC = GetDC(); ! 159: ! 160: dcMem.CreateCompatibleDC(pDC); ! 161: ! 162: m_pBitmap->CreateCompatibleBitmap(pDC, m_cxTotal, m_cyTotal); ! 163: ! 164: ASSERT(m_pBitmap->m_hObject != NULL); ! 165: ! 166: ReleaseDC(pDC); ! 167: ! 168: ! 169: CBitmap* pOldBitmap = dcMem.SelectObject(m_pBitmap); ! 170: ! 171: // draw a rectangle in the background (window) color ! 172: CRect rect(0, 0, m_cxTotal, m_cyTotal); ! 173: CBrush brBackground(::GetSysColor(COLOR_WINDOW)); ! 174: dcMem.FillRect(rect, &brBackground); ! 175: ! 176: CBrush brCross(HS_DIAGCROSS, 0L); ! 177: CBrush* pOldBrush = dcMem.SelectObject(&brCross); ! 178: ! 179: dcMem.SetBkColor(m_clrBall); ! 180: dcMem.Ellipse(ABS(m_cxMove), ABS(m_cyMove), ! 181: m_cxTotal - ABS(m_cxMove), m_cyTotal - ABS(m_cyMove)); ! 182: ! 183: dcMem.SelectObject(pOldBrush); ! 184: dcMem.SelectObject(pOldBitmap); ! 185: dcMem.DeleteDC(); ! 186: } ! 187: ! 188: // OnSize: ! 189: // The ball's size and displacement change according to the window size. ! 190: // ! 191: void CBounceWnd::OnSize(UINT nType, int cx, int cy) ! 192: { ! 193: LONG lScale; ! 194: ! 195: m_xCenter = (m_cxClient = cx) >> 1; ! 196: m_yCenter = (m_cyClient = cy) >> 1; ! 197: m_xCenter += m_cxClient >> 3; // make the ball a little off-center ! 198: ! 199: lScale = min((LONG)m_cxClient * m_xPixel, ! 200: (LONG)m_cyClient * m_yPixel) >> 4; ! 201: m_cxRadius = (short)(lScale / m_xPixel); ! 202: m_cyRadius = (short)(lScale / m_yPixel); ! 203: m_cxMove = max(1, m_cyRadius >> 2); ! 204: m_cyMove = max(1, m_cyRadius >> 2); ! 205: ! 206: MakeNewBall(); ! 207: ! 208: CMDIChildWnd::OnSize(nType, cx, cy); ! 209: } ! 210: ! 211: // OnColor: ! 212: // The ball's color needs to be changed. Checkmark the right color on the ! 213: // menu. ! 214: // ! 215: void CBounceWnd::OnColor() ! 216: { ! 217: CMenu* pMenu = m_pMDIFrameWnd->GetMenu(); ! 218: pMenu->CheckMenuItem(m_nColor, MF_UNCHECKED); ! 219: ! 220: m_nColor = GetCurrentMessage()->wParam; ! 221: pMenu->CheckMenuItem(m_nColor, MF_CHECKED); ! 222: ! 223: if (m_nColor != IDM_CUSTOM) ! 224: m_clrBall = clrTextArray[m_nColor - IDM_BLACK]; ! 225: else ! 226: { ! 227: CColorDialog dlgColor(m_clrBall); ! 228: if (dlgColor.DoModal() == IDOK) ! 229: m_clrBall = dlgColor.GetColor(); ! 230: } ! 231: ! 232: MakeNewBall(); ! 233: ! 234: Invalidate(); ! 235: } ! 236: ! 237: // OnSpeed: ! 238: // The ball's speed needs to be changed. Checkmark the menus, kill the ! 239: // current timer and start a new one at the new speed. ! 240: // ! 241: void CBounceWnd::OnSpeed() ! 242: { ! 243: CMenu* pMenu = m_pMDIFrameWnd->GetMenu(); ! 244: pMenu->CheckMenuItem(m_nSpeed, MF_UNCHECKED); ! 245: ! 246: m_nSpeed = GetCurrentMessage()->wParam; ! 247: pMenu->CheckMenuItem(m_nSpeed, MF_CHECKED); ! 248: ! 249: KillTimer(1); ! 250: if (!SetTimer(1, (m_nSpeed==IDM_SLOW? 100 : 0), NULL)) ! 251: { ! 252: MessageBox("Not enough timers available for this window.", ! 253: "MDI:Bounce", MB_ICONEXCLAMATION | MB_OK); ! 254: ! 255: m_nSpeed = 0; ! 256: ! 257: DestroyWindow(); ! 258: } ! 259: } ! 260: ! 261: // OnTimer: ! 262: // Animate the ball. ! 263: // ! 264: void CBounceWnd::OnTimer(UINT /* wParam */) ! 265: { ! 266: if (m_pBitmap != NULL) ! 267: { ! 268: CDC dcMem; ! 269: CDC* pdcScreen = NULL; ! 270: CBitmap* pOldMap = NULL; ! 271: ! 272: pdcScreen = GetDC(); ! 273: ! 274: dcMem.CreateCompatibleDC(pdcScreen); ! 275: ! 276: ASSERT(m_pBitmap->m_hObject != NULL); ! 277: ! 278: pOldMap = dcMem.SelectObject(m_pBitmap); ! 279: ! 280: pdcScreen->BitBlt(m_xCenter - m_cxTotal / 2, ! 281: m_yCenter - m_cyTotal / 2, m_cxTotal, m_cyTotal, ! 282: &dcMem, 0, 0, SRCCOPY); ! 283: ! 284: ReleaseDC(pdcScreen); ! 285: ! 286: m_xCenter += m_cxMove; ! 287: m_yCenter += m_cyMove; ! 288: ! 289: if ((m_xCenter + m_cxRadius >= m_cxClient) || ! 290: (m_xCenter - m_cxRadius <= 0)) ! 291: { ! 292: m_cxMove = -m_cxMove; ! 293: } ! 294: ! 295: if ((m_yCenter + m_cyRadius >= m_cyClient) || ! 296: (m_yCenter - m_cyRadius <= 0)) ! 297: { ! 298: m_cyMove = -m_cyMove; ! 299: } ! 300: ! 301: dcMem.SelectObject(pOldMap); ! 302: dcMem.DeleteDC(); ! 303: } ! 304: } ! 305: ! 306: // OnMDIActivate: ! 307: // The current window is being activated or deactivated. ! 308: // Change MDI frame window menu as appropriate. ! 309: // ! 310: ! 311: void CBounceWnd::OnMDIActivate(BOOL bActivate, CWnd* /*pActive*/, ! 312: CWnd* /*pDeActive*/) ! 313: { ! 314: ! 315: CMDIFrameWnd* pFrame = m_pMDIFrameWnd; ! 316: CMenu* pWinPopupMenu = NULL; ! 317: CMenu* pMenu = NULL; ! 318: ! 319: m_bWindowActive = bActivate; ! 320: ! 321: if (bActivate) ! 322: { ! 323: pMenu = new CMenu; ! 324: pMenu->LoadMenu("MdiMenuBounce"); ! 325: pWinPopupMenu = pMenu->GetSubMenu(BOUNCE_MENU_POS); ! 326: ! 327: CMenu* pLastMenu = pFrame->MDISetMenu(pMenu, pWinPopupMenu); ! 328: pLastMenu->DestroyMenu(); ! 329: ! 330: pMenu->CheckMenuItem(m_nColor, bActivate ? MF_CHECKED : MF_UNCHECKED); ! 331: pMenu->CheckMenuItem(m_nSpeed, bActivate ? MF_CHECKED : MF_UNCHECKED); ! 332: ! 333: delete m_pMenuCurrent; ! 334: m_pMenuCurrent = pMenu; ! 335: ! 336: } ! 337: else ! 338: { ! 339: pMenu = new CMenu; ! 340: pMenu->LoadMenu("MdiMenuInit"); ! 341: pWinPopupMenu = pMenu->GetSubMenu(INIT_MENU_POS); ! 342: ! 343: CMenu* pLastMenu = pFrame->MDISetMenu(pMenu, pWinPopupMenu); ! 344: pLastMenu->DestroyMenu(); ! 345: ! 346: delete m_pMenuCurrent; ! 347: m_pMenuCurrent = pMenu; ! 348: } ! 349: ! 350: pFrame->DrawMenuBar(); ! 351: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.