|
|
1.1 ! root 1: // This is a part of the Microsoft Foundation Classes C++ library. ! 2: // Copyright (C) 1992 Microsoft Corporation ! 3: // All rights reserved. ! 4: // ! 5: // This source code is only intended as a supplement to the ! 6: // Microsoft Foundation Classes Reference and Microsoft ! 7: // QuickHelp documentation provided with the library. ! 8: // See these sources for detailed information regarding the ! 9: // Microsoft Foundation Classes product. ! 10: ! 11: ! 12: #include "afxwin.h" ! 13: #pragma hdrstop ! 14: ! 15: #include "winhand_.h" ! 16: #include "window_.h" ! 17: ! 18: #ifdef AFX_CORE_SEG ! 19: #pragma code_seg(AFX_CORE_SEG) ! 20: #endif ! 21: ! 22: #ifdef _DEBUG ! 23: #include "trace_.h" ! 24: #undef THIS_FILE ! 25: static char BASED_CODE THIS_FILE[] = __FILE__; ! 26: #define new DEBUG_NEW ! 27: #endif ! 28: ! 29: ///////////////////////////////////////////////////////////////////////////// ! 30: // CHandleMap implementation ! 31: ! 32: CObject* ! 33: CHandleMap::FromHandle(HANDLE h) ! 34: { ! 35: if (h == NULL) ! 36: return NULL; ! 37: ! 38: void* p; ! 39: if (LookupPermanent(h, p)) ! 40: return (CObject*)p; // return permanent one ! 41: else if (LookupTemporary(h, p)) ! 42: return (CObject*)p; // return last temporary one ! 43: ! 44: // This handle wasn't created by us, so we must create a temporary ! 45: // C++ object to wrap it. We don't want the user to see this memory ! 46: // allocation, so we turn tracing off. ! 47: #ifdef _DEBUG ! 48: BOOL bEnable = AfxEnableMemoryTracking(FALSE); ! 49: #endif ! 50: CObject* pTemp = NewTempObject(h); ! 51: #ifdef _NTWIN ! 52: temporaryMap.SetAt((LPVOID)h, pTemp); ! 53: #else ! 54: temporaryMap.SetAt((WORD)h, pTemp); ! 55: #endif ! 56: #ifdef _DEBUG ! 57: AfxEnableMemoryTracking(bEnable); ! 58: #endif ! 59: return pTemp; ! 60: } ! 61: ! 62: void ! 63: CHandleMap::DeleteTemp() ! 64: { ! 65: POSITION pos = temporaryMap.GetStartPosition(); ! 66: while (pos != NULL) ! 67: { ! 68: #ifdef _NTWIN ! 69: LPVOID h; // not used ! 70: #else ! 71: WORD h; // not used ! 72: #endif ! 73: void* p; ! 74: temporaryMap.GetNextAssoc(pos, h, p); ! 75: DeleteTempObject((CObject*)p); // free it up ! 76: } ! 77: ! 78: temporaryMap.RemoveAll(); // free up dictionary links etc ! 79: } ! 80: ! 81: ///////////////////////////////////////////////////////////////////////////// ! 82: IMPLEMENT_DYNAMIC(CButton, CWnd) ! 83: IMPLEMENT_DYNAMIC(CListBox, CWnd) ! 84: IMPLEMENT_DYNAMIC(CComboBox, CWnd) ! 85: ! 86: IMPLEMENT_DYNAMIC(CWnd, CObject) ! 87: ! 88: ! 89: char NEAR _afxWnd[] = "AfxWnd"; ! 90: char NEAR _afxMDIFrameWnd[] = "AfxMDIFrameWnd"; ! 91: char NEAR _afxFrameWnd[] = "AfxFrameWnd"; ! 92: ! 93: ! 94: ///////////////////////////////////////////////////////////////////////////// ! 95: // Special bootstrap globals ! 96: ! 97: static CWnd* pWndInit = NULL; ! 98: static CDialog* pDlgInit = NULL; ! 99: ! 100: ///////////////////////////////////////////////////////////////////////////// ! 101: // Official way to send message to a CWnd ! 102: ! 103: struct CLastState ! 104: { ! 105: MSG msg; ! 106: }; ! 107: static CLastState NEAR lastState; ! 108: // global for last state of call to 'WindowProc' ! 109: ! 110: LONG _AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT message, ! 111: UINT wParam, LONG lParam) ! 112: { ! 113: LONG lResult; ! 114: CLastState oldState = lastState; // save for nesting ! 115: ! 116: lastState.msg.hwnd = hWnd; ! 117: lastState.msg.message = message; ! 118: lastState.msg.wParam = wParam; ! 119: lastState.msg.lParam = lParam; ! 120: ! 121: #ifdef _DEBUG ! 122: if (afxTraceFlags & 4) ! 123: AfxTraceMsg("WndProc", &lastState.msg); ! 124: #endif ! 125: ! 126: // Catch exceptions thrown outside the scope of a callback ! 127: // in debug builds and warn the user. ! 128: TRY ! 129: { ! 130: lResult = pWnd->WindowProc(message, wParam, lParam); ! 131: } ! 132: CATCH (CException, e) ! 133: { ! 134: if (message == WM_CREATE) ! 135: lResult = -1; ! 136: else ! 137: lResult = 0; ! 138: TRACE("Warning: Uncaught exception in WindowProc (returning %ld)\n", ! 139: lResult); ! 140: ASSERT(FALSE); ! 141: } ! 142: END_CATCH ! 143: ! 144: lastState = oldState; ! 145: return lResult; ! 146: } ! 147: ! 148: const MSG* CWnd::GetCurrentMessage() ! 149: { ! 150: // fill in time and position when asked for ! 151: lastState.msg.time = ::GetMessageTime(); ! 152: *((DWORD*)&lastState.msg.pt) = ::GetMessagePos(); ! 153: return &lastState.msg; ! 154: } ! 155: ! 156: LONG CWnd::Default() ! 157: // call DefWindowProc with the last message ! 158: { ! 159: return DefWindowProc(lastState.msg.message, ! 160: lastState.msg.wParam, lastState.msg.lParam); ! 161: } ! 162: ! 163: ///////////////////////////////////////////////////////////////////////////// ! 164: // Map from HWND to CWnd* ! 165: ! 166: class NEAR CWndHandleMap : public CHandleMap ! 167: { ! 168: public: ! 169: CObject* NewTempObject(HANDLE h) ! 170: { ! 171: // don't add in permanent ! 172: CWnd* p = new CWnd(); ! 173: p->m_hWnd = (HWND)h; // set after constructed ! 174: return p; ! 175: } ! 176: void DeleteTempObject(CObject* ob) ! 177: { ! 178: ASSERT(ob->IsKindOf(RUNTIME_CLASS(CWnd))); ! 179: ((CWnd*)ob)->m_hWnd = NULL; // clear before destructed ! 180: delete ob; ! 181: } ! 182: CWndHandleMap() ! 183: { } ! 184: }; ! 185: static CWndHandleMap NEAR hWndMap; ! 186: ! 187: CWnd* ! 188: CWnd::FromHandle(HWND hWnd) ! 189: { ! 190: return (CWnd*)hWndMap.FromHandle(hWnd); ! 191: } ! 192: ! 193: CWnd* ! 194: CWnd::FromHandlePermanent(HWND hWnd) ! 195: { ! 196: // only look in the permanent map - does no allocations ! 197: void* p; ! 198: return (hWndMap.LookupPermanent(hWnd, p)) ? (CWnd*)p : NULL; ! 199: } ! 200: ! 201: void ! 202: CWnd::DeleteTempMap() ! 203: { ! 204: hWndMap.DeleteTemp(); ! 205: } ! 206: ! 207: BOOL ! 208: CWnd::Attach(HWND hWnd) ! 209: { ! 210: ASSERT(m_hWnd == NULL); // only attach once, detach on destroy ! 211: if (hWnd == NULL) ! 212: return FALSE; ! 213: hWndMap.SetPermanent(m_hWnd = hWnd, this); ! 214: return TRUE; ! 215: } ! 216: ! 217: HWND ! 218: CWnd::Detach() ! 219: { ! 220: HWND hWnd; ! 221: if ((hWnd = m_hWnd) != NULL) ! 222: hWndMap.RemovePermanent(m_hWnd); ! 223: m_hWnd = NULL; ! 224: return hWnd; ! 225: } ! 226: ! 227: ! 228: ///////////////////////////////////////////////////////////////////////////// ! 229: // One main WndProc for all CWnd's and derived classes ! 230: ! 231: LONG FAR PASCAL AFX_EXPORT ! 232: AfxWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam) ! 233: { ! 234: register CWnd* pWnd; ! 235: ! 236: pWnd = CWnd::FromHandlePermanent(hWnd); ! 237: ASSERT(pWnd != NULL); ! 238: ASSERT(pWnd->m_hWnd == hWnd); ! 239: ! 240: LONG lResult = _AfxCallWndProc(pWnd, hWnd, message, wParam, lParam); ! 241: ! 242: return lResult; ! 243: } ! 244: ! 245: // Special case for remaining dialog cases ! 246: // Most messages will go through the window proc (AfxWndProc) of the ! 247: // subclassed dialog. Some messages like WM_SETFONT and WM_INITDIALOG ! 248: // are sent directly to the dialog proc only. These messages cannot be ! 249: // passed on to DefWindowProc() or infinite recursion will result! ! 250: // In responding to these messages, you shouldn't call the Default handler ! 251: LONG FAR PASCAL AFX_EXPORT ! 252: _AfxDlgProc(HWND hWnd, register UINT message, UINT wParam, LONG lParam) ! 253: { ! 254: register CDialog* pDlg; ! 255: ! 256: // test for special case (Win 3.0 will call dialog proc instead ! 257: // of SendMessage for these two messages). ! 258: if (message != WM_SETFONT && message != WM_INITDIALOG) ! 259: return 0L; // normal handler ! 260: ! 261: // assume it is already wired up to a permanent one ! 262: pDlg = (CDialog*) CWnd::FromHandlePermanent(hWnd); ! 263: ASSERT(pDlg != NULL); ! 264: ASSERT(pDlg->m_hWnd == hWnd); ! 265: ! 266: // prepare for callback, make it look like message map call ! 267: LONG lResult = 0; ! 268: CLastState oldState = lastState; // save for nesting ! 269: ! 270: lastState.msg.hwnd = hWnd; ! 271: lastState.msg.message = message; ! 272: lastState.msg.wParam = wParam; ! 273: lastState.msg.lParam = lParam; ! 274: ! 275: TRY ! 276: { ! 277: if (message == WM_SETFONT) ! 278: pDlg->OnSetFont(CFont::FromHandle((HFONT)wParam)); ! 279: else // WM_INITDIALOG ! 280: lResult = pDlg->OnInitDialog(); ! 281: } ! 282: CATCH (CException, e) ! 283: { ! 284: // fall through ! 285: TRACE("Warning: something went wrong in dialog init\n"); ! 286: pDlg->EndDialog(IDCANCEL); // something went wrong ! 287: ASSERT(FALSE); ! 288: } ! 289: END_CATCH ! 290: ! 291: lastState = oldState; ! 292: return lResult; ! 293: } ! 294: ! 295: ///////////////////////////////////////////////////////////////////////////// ! 296: // Window creation hook ! 297: #ifdef STRICT ! 298: static HHOOK pfnOldSendMsgHook = NULL; ! 299: #else ! 300: static HOOKPROC pfnOldSendMsgHook = NULL; ! 301: #endif ! 302: ! 303: #pragma optimize("q", off) // disable pcode opt (Win 3.0 compatibility) ! 304: ! 305: void FAR PASCAL AFX_EXPORT ! 306: _AfxSendMsgHook(int code, UINT wParam, LONG lParam) ! 307: { ! 308: struct HOOKINFO // Hook info struct passed by send message hook ! 309: { ! 310: LONG lParam; ! 311: UINT wParam; ! 312: UINT msg; ! 313: HWND hWnd; ! 314: }; ! 315: HOOKINFO FAR* hookInfo; ! 316: ! 317: if (code < 0) ! 318: { ! 319: ::DefHookProc(code, wParam, lParam, &pfnOldSendMsgHook); ! 320: return; ! 321: } ! 322: ! 323: ASSERT(pWndInit != NULL); ! 324: hookInfo = (HOOKINFO FAR*)lParam; ! 325: HWND hWnd = hookInfo->hWnd; ! 326: ! 327: // ignore non-creation messages ! 328: if (hookInfo->msg != WM_GETMINMAXINFO && ! 329: hookInfo->msg != WM_NCCREATE) ! 330: { ! 331: // not being constructed ! 332: return; ! 333: } ! 334: ! 335: // Connect the HWND to pWndInit... ! 336: pWndInit->Attach(hWnd); ! 337: ! 338: // Subclass the window by replacing its window proc addr... ! 339: WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, ! 340: (DWORD)AfxWndProc); ! 341: if (oldWndProc != (WNDPROC)AfxWndProc) ! 342: { ! 343: *(pWndInit->GetSuperWndProcAddr()) = oldWndProc; // save if not default ! 344: } ! 345: ! 346: // Unhook the send message hook since we don't need it any more ! 347: ::UnhookWindowsHook(WH_CALLWNDPROC, (HOOKPROC)_AfxSendMsgHook); ! 348: pWndInit = NULL; ! 349: } ! 350: ! 351: #pragma optimize("", on) // return to default optimizations ! 352: ! 353: void _AfxHookWindowCreate(register CWnd* pWnd) ! 354: { ! 355: #ifndef _WINDLL ! 356: if (_afxSetWindowsHookExProc == NULL) ! 357: { ! 358: pfnOldSendMsgHook = ::SetWindowsHook(WH_CALLWNDPROC, ! 359: (HOOKPROC)_AfxSendMsgHook); ! 360: } ! 361: else ! 362: { ! 363: #ifdef STRICT ! 364: #ifdef _NTWIN ! 365: pfnOldSendMsgHook = (HHOOK)(*_afxSetWindowsHookExProc)( ! 366: WH_CALLWNDPROC, (HOOKPROC)_AfxSendMsgHook, NULL, 0); ! 367: #else ! 368: pfnOldSendMsgHook = (HHOOK)(*_afxSetWindowsHookExProc)( ! 369: WH_CALLWNDPROC, (HOOKPROC)_AfxSendMsgHook, AfxGetInstanceHandle(), ! 370: GetCurrentTask()); ! 371: #endif ! 372: #else ! 373: #ifdef _NTWIN ! 374: pfnOldSendMsgHook = (HOOKPROC)(*_afxSetWindowsHookExProc)( ! 375: WH_CALLWNDPROC, (HOOKPROC)_AfxSendMsgHook, NULL, 0); ! 376: #else ! 377: pfnOldSendMsgHook = (HOOKPROC)(*_afxSetWindowsHookExProc)( ! 378: WH_CALLWNDPROC, (HOOKPROC)_AfxSendMsgHook, AfxGetInstanceHandle(), ! 379: GetCurrentTask()); ! 380: #endif ! 381: #endif ! 382: } ! 383: #else // _WINDLL ! 384: pfnOldSendMsgHook = ::SetWindowsHook(WH_CALLWNDPROC, ! 385: (HOOKPROC)_AfxSendMsgHook); ! 386: #endif // _WINDLL ! 387: ! 388: ASSERT(pWnd != NULL); ! 389: ASSERT(pWnd->m_hWnd == NULL); // only do once ! 390: ! 391: ASSERT(pWndInit == NULL); // hook not already in progress ! 392: pWndInit = pWnd; ! 393: } ! 394: ! 395: BOOL _AfxUnhookWindowCreate() ! 396: // return TRUE if already unhooked ! 397: { ! 398: if (pWndInit == NULL) ! 399: return TRUE; // already unhooked => window create success ! 400: ::UnhookWindowsHook(WH_CALLWNDPROC, (HOOKPROC)_AfxSendMsgHook); ! 401: pWndInit = NULL; ! 402: return FALSE; ! 403: } ! 404: ! 405: ///////////////////////////////////////////////////////////////////////////// ! 406: // CWnd creation ! 407: ! 408: BOOL CWnd::CreateEx(DWORD dwExStyle, LPCSTR lpClassName, ! 409: LPCSTR lpWindowName, DWORD dwStyle, ! 410: int x, int y, int nWidth, int nHeight, ! 411: HWND hWndParent, HMENU nIDorHMenu) ! 412: { ! 413: _AfxHookWindowCreate(this); ! 414: HWND hWnd = ::CreateWindowEx(dwExStyle, lpClassName, ! 415: lpWindowName, dwStyle, x, y, nWidth, nHeight, ! 416: hWndParent, nIDorHMenu, AfxGetInstanceHandle(), NULL); ! 417: ! 418: _AfxUnhookWindowCreate(); ! 419: if (hWnd == NULL) ! 420: return NULL; ! 421: ASSERT(hWnd == m_hWnd); // should have been set in send msg hook ! 422: return TRUE; ! 423: } ! 424: ! 425: // for child windows ! 426: BOOL CWnd::Create(LPCSTR lpClassName, ! 427: LPCSTR lpWindowName, DWORD dwStyle, ! 428: const RECT& rect, ! 429: const CWnd* pParentWnd, UINT nID) ! 430: { ! 431: ASSERT(pParentWnd != NULL); ! 432: ! 433: if (lpClassName == NULL) ! 434: lpClassName = _afxWnd; ! 435: ! 436: return CreateEx(0, lpClassName, lpWindowName, ! 437: dwStyle | WS_CHILD, ! 438: rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, ! 439: pParentWnd->GetSafeHwnd(), (HMENU)nID); ! 440: } ! 441: ! 442: CWnd::~CWnd() ! 443: { ! 444: DestroyWindow(); ! 445: } ! 446: ! 447: ! 448: #ifdef _NTWIN ! 449: struct _AFXCTLCOLOR { ! 450: HWND hWnd; ! 451: HDC hDC; ! 452: UINT nCtlType; ! 453: }; ! 454: ! 455: LRESULT CWnd::OnNTCtlColor(WPARAM wParam, LPARAM lParam) ! 456: { ! 457: struct _AFXCTLCOLOR ctl; ! 458: ! 459: ctl.hDC = (HDC)wParam; ! 460: ctl.hWnd = (HWND)lParam; ! 461: ctl.nCtlType = GetCurrentMessage()->message - WM_CTLCOLORMSGBOX; ! 462: ! 463: ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX); ! 464: ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC); ! 465: ! 466: return SendMessage(WM_CTLCOLOR, 0, (LPARAM)&ctl); ! 467: } ! 468: #endif ! 469: ! 470: void CWnd::OnDestroy() ! 471: { ! 472: #ifndef _WINDLL ! 473: // Automatically quit when the main window is destroyed. ! 474: if (AfxGetApp()->m_pMainWnd == this) ! 475: ::PostQuitMessage(0); ! 476: #endif // _WINDLL ! 477: Default(); ! 478: } ! 479: ! 480: void CWnd::OnNcDestroy() ! 481: { ! 482: // WM_NCDESTROY is the absolute LAST message sent. ! 483: if (AfxGetApp()->m_pMainWnd == this) ! 484: AfxGetApp()->m_pMainWnd = NULL; ! 485: ! 486: Default(); ! 487: Detach(); ! 488: ASSERT(m_hWnd == NULL); ! 489: ! 490: // call special post-cleanup routine ! 491: PostNcDestroy(); ! 492: } ! 493: ! 494: void CWnd::PostNcDestroy() ! 495: { ! 496: // default to nothing ! 497: } ! 498: ! 499: #ifdef _DEBUG ! 500: void CWnd::AssertValid() const ! 501: { ! 502: ASSERT(m_hWnd == NULL || ! 503: (m_hWnd == (HWND)1 && this == &CWnd::wndBottom) || ! 504: ::IsWindow(m_hWnd)); ! 505: void* p; ! 506: ASSERT(m_hWnd == NULL || ! 507: (m_hWnd == (HWND)1 && this == &CWnd::wndBottom) || ! 508: hWndMap.LookupPermanent(m_hWnd, p) || ! 509: hWndMap.LookupTemporary(m_hWnd, p)); ! 510: } ! 511: ! 512: void CWnd::Dump(CDumpContext& dc) const ! 513: { ! 514: CObject::Dump(dc); ! 515: ! 516: dc << "with window information:\n"; ! 517: dc << "m_hWnd = " << (void NEAR*)m_hWnd; ! 518: ! 519: if ((UINT)m_hWnd > 1) ! 520: { ! 521: char szBuf [64]; ! 522: ! 523: GetWindowText(szBuf, sizeof (szBuf)); ! 524: dc << "\ncaption = \"" << szBuf << "\""; ! 525: ! 526: ::GetClassName(m_hWnd, szBuf, sizeof (szBuf)); ! 527: dc << "\nclass name = \"" << szBuf << "\""; ! 528: ! 529: CRect rect; ! 530: GetWindowRect(&rect); ! 531: dc << "\nrect = " << rect; ! 532: ! 533: dc << "\nparent CWnd* = " << (void*)GetParent(); ! 534: ! 535: dc << "\nstyle = " << (void FAR*)::GetWindowLong(m_hWnd, GWL_STYLE); ! 536: if (::GetWindowLong(m_hWnd, GWL_STYLE) & WS_CHILD) ! 537: dc << "\nid = " << ::GetWindowWord(m_hWnd, GWW_ID); ! 538: } ! 539: } ! 540: #endif ! 541: ! 542: BOOL ! 543: CWnd::DestroyWindow() ! 544: { ! 545: if (m_hWnd == NULL) ! 546: return FALSE; ! 547: ! 548: void* p; ! 549: BOOL bInPermanentMap = hWndMap.LookupPermanent(m_hWnd, p); ! 550: BOOL bRet = ::DestroyWindow(m_hWnd); ! 551: // Note that 'this' may have been deleted at this point. ! 552: if (bInPermanentMap) ! 553: { ! 554: // Should have been detached by OnNcDestroy ! 555: ASSERT(!hWndMap.LookupPermanent(m_hWnd, p)); ! 556: } ! 557: else ! 558: { ! 559: // Detach after DestroyWindow called just in case ! 560: Detach(); ! 561: } ! 562: return bRet; ! 563: } ! 564: ! 565: ///////////////////////////////////////////////////////////////////////////// ! 566: // Default CWnd implementation ! 567: ! 568: LONG CWnd::DefWindowProc(UINT nMsg, UINT wParam, LONG lParam) ! 569: { ! 570: WNDPROC pfnWndProc; ! 571: ! 572: if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL) ! 573: return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam); ! 574: else ! 575: #ifdef STRICT ! 576: return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam); ! 577: #else ! 578: return ::CallWindowProc((FARPROC)pfnWndProc, m_hWnd, nMsg, wParam, lParam); ! 579: #endif ! 580: } ! 581: ! 582: WNDPROC* CWnd::GetSuperWndProcAddr() ! 583: { ! 584: static WNDPROC pfnSuper = NULL; ! 585: ASSERT(pfnSuper == NULL); // should never be changed !!! ! 586: // if this is non-NULL, then a derived class of CWnd ! 587: // forgot to override 'superWndProc' as well as 'className' ! 588: return &pfnSuper; ! 589: } ! 590: ! 591: BOOL CWnd::PreTranslateMessage(MSG*) ! 592: { ! 593: // no default processing ! 594: return FALSE; ! 595: } ! 596: ! 597: ///////////////////////////////////////////////////////////////////////////// ! 598: // CWnd will delegate owner draw messages to self drawing controls ! 599: ! 600: // Drawing: for all 4 control types ! 601: void CWnd::OnDrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) ! 602: { ! 603: UINT nType; ! 604: if ((nType = lpDrawItemStruct->CtlType) == ODT_MENU) ! 605: { ! 606: CMenu* pMenu = CMenu::FromHandle((HMENU)lpDrawItemStruct->hwndItem); ! 607: if (pMenu != NULL) ! 608: { ! 609: pMenu->DrawItem(lpDrawItemStruct); ! 610: return; ! 611: } ! 612: } ! 613: else ! 614: { ! 615: CWnd* pChild = CWnd::FromHandlePermanent(lpDrawItemStruct->hwndItem); ! 616: if (pChild != NULL) ! 617: { ! 618: if (nType == ODT_BUTTON && ! 619: pChild->IsKindOf(RUNTIME_CLASS(CButton))) ! 620: { ! 621: ((CButton*)pChild)->DrawItem(lpDrawItemStruct); ! 622: return; ! 623: } ! 624: else if (nType == ODT_LISTBOX && ! 625: pChild->IsKindOf(RUNTIME_CLASS(CListBox))) ! 626: { ! 627: ((CListBox*)pChild)->DrawItem(lpDrawItemStruct); ! 628: return; ! 629: } ! 630: else if (nType == ODT_COMBOBOX && ! 631: pChild->IsKindOf(RUNTIME_CLASS(CComboBox))) ! 632: { ! 633: ((CComboBox*)pChild)->DrawItem(lpDrawItemStruct); ! 634: return; ! 635: } ! 636: } ! 637: } ! 638: // not handled - do default ! 639: Default(); ! 640: } ! 641: ! 642: // Drawing: for all 4 control types ! 643: int CWnd::OnCompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct) ! 644: { ! 645: CWnd* pChild = CWnd::FromHandlePermanent(lpCompareItemStruct->hwndItem); ! 646: if (pChild != NULL) ! 647: { ! 648: UINT nType = lpCompareItemStruct->CtlType; ! 649: if (nType == ODT_LISTBOX && ! 650: pChild->IsKindOf(RUNTIME_CLASS(CListBox))) ! 651: { ! 652: return ((CListBox*)pChild)->CompareItem(lpCompareItemStruct); ! 653: } ! 654: else if (nType == ODT_COMBOBOX && ! 655: pChild->IsKindOf(RUNTIME_CLASS(CComboBox))) ! 656: { ! 657: return ((CComboBox*)pChild)->CompareItem(lpCompareItemStruct); ! 658: } ! 659: } ! 660: // not handled - do default ! 661: return (int)Default(); ! 662: } ! 663: ! 664: void CWnd::OnDeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct) ! 665: { ! 666: CWnd* pChild = CWnd::FromHandlePermanent(lpDeleteItemStruct->hwndItem); ! 667: if (pChild != NULL) ! 668: { ! 669: UINT nType = lpDeleteItemStruct->CtlType; ! 670: if (nType == ODT_LISTBOX && ! 671: pChild->IsKindOf(RUNTIME_CLASS(CListBox))) ! 672: { ! 673: ((CListBox*)pChild)->DeleteItem(lpDeleteItemStruct); ! 674: return; ! 675: } ! 676: else if (nType == ODT_COMBOBOX && ! 677: pChild->IsKindOf(RUNTIME_CLASS(CComboBox))) ! 678: { ! 679: ((CComboBox*)pChild)->DeleteItem(lpDeleteItemStruct); ! 680: return; ! 681: } ! 682: } ! 683: // not handled - do default ! 684: Default(); ! 685: } ! 686: ! 687: ! 688: static CMenu* FindPopupMenuFromID(CMenu* pMenu, UINT nID) ! 689: { ! 690: // walk through all items, looking for ID match ! 691: UINT nItems = pMenu->GetMenuItemCount(); ! 692: for (int iItem = 0; iItem < (int)nItems; iItem++) ! 693: { ! 694: if (pMenu->GetMenuState(iItem, MF_BYPOSITION) & MF_POPUP) ! 695: { ! 696: // recurse to child popup ! 697: CMenu* pPopup = FindPopupMenuFromID(pMenu->GetSubMenu(iItem), nID); ! 698: // try recursing ! 699: if (pPopup != NULL) ! 700: return pPopup; ! 701: } ! 702: else if (pMenu->GetMenuItemID(iItem) == nID) ! 703: { ! 704: // it is a normal item inside our popup ! 705: return pMenu; ! 706: } ! 707: } ! 708: // not found ! 709: return NULL; ! 710: } ! 711: ! 712: // Measure item implementation relies on unique control/menu IDs ! 713: void CWnd::OnMeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) ! 714: { ! 715: UINT nType; ! 716: if ((nType = lpMeasureItemStruct->CtlType) == ODT_MENU) ! 717: { ! 718: ASSERT(lpMeasureItemStruct->CtlID == 0); ! 719: CMenu* pMenu = FindPopupMenuFromID(GetMenu(), ! 720: lpMeasureItemStruct->itemID); ! 721: if (pMenu != NULL) ! 722: { ! 723: pMenu->MeasureItem(lpMeasureItemStruct); ! 724: return; ! 725: } ! 726: else ! 727: { ! 728: TRACE("Warning: unknown WM_MEASUREITEM request for" ! 729: " menu item 0x%04X\n", lpMeasureItemStruct->itemID); ! 730: } ! 731: } ! 732: else ! 733: { ! 734: HWND hWndChild = ::GetDlgItem(m_hWnd, lpMeasureItemStruct->CtlID); ! 735: CWnd* pChild; ! 736: if (hWndChild != NULL && ! 737: (pChild = CWnd::FromHandlePermanent(hWndChild)) != NULL) ! 738: { ! 739: if (nType == ODT_LISTBOX && ! 740: pChild->IsKindOf(RUNTIME_CLASS(CListBox))) ! 741: { ! 742: ((CListBox*)pChild)->MeasureItem(lpMeasureItemStruct); ! 743: return; ! 744: } ! 745: else if (nType == ODT_COMBOBOX && ! 746: pChild->IsKindOf(RUNTIME_CLASS(CComboBox))) ! 747: { ! 748: ((CComboBox*)pChild)->MeasureItem(lpMeasureItemStruct); ! 749: return; ! 750: } ! 751: } ! 752: } ! 753: // not handled - do default ! 754: Default(); ! 755: } ! 756: ! 757: ///////////////////////////////////////////////////////////////////////////// ! 758: // CFrameWnd ! 759: ! 760: IMPLEMENT_DYNAMIC(CFrameWnd, CWnd) ! 761: ! 762: CFrameWnd::CFrameWnd() ! 763: { ! 764: ASSERT(m_hWnd == NULL); ! 765: m_hAccelTable = NULL; ! 766: } ! 767: ! 768: CFrameWnd::~CFrameWnd() ! 769: { ! 770: if (m_hAccelTable != NULL) ! 771: ::FreeResource(m_hAccelTable); ! 772: } ! 773: ! 774: void CFrameWnd::PostNcDestroy() ! 775: { ! 776: // default for frame windows is to allocate them on the heap ! 777: // the default post-cleanup is to 'delete this'. ! 778: // never explicitly call 'delete' on a CFrameWnd, use DestroyWindow instead ! 779: delete this; ! 780: } ! 781: ! 782: #ifdef _DEBUG ! 783: void CFrameWnd::AssertValid() const ! 784: { ! 785: CWnd::AssertValid(); ! 786: } ! 787: ! 788: void CFrameWnd::Dump(CDumpContext& dc) const ! 789: { ! 790: CWnd::Dump(dc); ! 791: dc << "\nm_hAccelTable = " << (UINT) m_hAccelTable; ! 792: } ! 793: #endif ! 794: ! 795: BOOL CFrameWnd::LoadAccelTable(LPCSTR lpAccelTableName) ! 796: { ! 797: ASSERT(m_hAccelTable == NULL); // only do once ! 798: ASSERT(lpAccelTableName != NULL); ! 799: ! 800: m_hAccelTable = ::LoadAccelerators(AfxGetResourceHandle(), ! 801: lpAccelTableName); ! 802: return (m_hAccelTable != NULL); ! 803: } ! 804: ! 805: ///////////////////////////////////////////////////////////////////////////// ! 806: // Creation and window tree access ! 807: ! 808: BOOL CFrameWnd::Create(LPCSTR lpClassName, ! 809: LPCSTR lpWindowName, ! 810: DWORD dwStyle, const RECT& rect, ! 811: const CWnd* pParentWnd, ! 812: LPCSTR lpMenuName) ! 813: { ! 814: HMENU hMenu = NULL; ! 815: ! 816: if (lpClassName == NULL) ! 817: lpClassName = _afxFrameWnd; ! 818: ! 819: if (lpMenuName != NULL) ! 820: { ! 821: // load in a menu that will get destroyed when window gets destroyed ! 822: hMenu = ::LoadMenu(AfxGetResourceHandle(), lpMenuName); ! 823: if (hMenu == NULL) ! 824: { ! 825: TRACE("Warning: failed to load menu for CFrameWnd\n"); ! 826: return FALSE; ! 827: } ! 828: } ! 829: ! 830: if (!CreateEx(0L, lpClassName, lpWindowName, dwStyle, ! 831: rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, ! 832: pParentWnd->GetSafeHwnd(), hMenu)) ! 833: { ! 834: TRACE("Warning: failed to create CFrameWnd\n"); ! 835: return FALSE; ! 836: } ! 837: return TRUE; ! 838: } ! 839: ! 840: CFrameWnd* CFrameWnd::GetChildFrame() ! 841: { ! 842: return this; ! 843: } ! 844: ! 845: CFrameWnd* CFrameWnd::GetParentFrame() ! 846: { ! 847: return this; ! 848: } ! 849: ! 850: BOOL CFrameWnd::PreTranslateMessage(MSG* pMsg) ! 851: { ! 852: return (m_hAccelTable != NULL && ! 853: ::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg)); ! 854: } ! 855: ! 856: ! 857: ///////////////////////////////////////////////////////////////////////////// ! 858: // Additional helpers for WNDCLASS init ! 859: ! 860: const char* AfxRegisterWndClass(UINT nClassStyle, ! 861: HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon) ! 862: { ! 863: // Returns a temporary string name for the class ! 864: // Save in a CString if you want to use it for a long time ! 865: WNDCLASS wndcls; ! 866: static char szName[64]; // 1 global string ! 867: ! 868: // generate a synthetic name for this class ! 869: if (hCursor == NULL && hbrBackground == NULL && hIcon == NULL) ! 870: wsprintf(szName, "Afx:%x", nClassStyle); ! 871: else ! 872: wsprintf(szName, "Afx:%x:%x:%x:%x", nClassStyle, ! 873: (UINT) hCursor, (UINT) hbrBackground, (UINT) hIcon); ! 874: ! 875: // see if the class already exists ! 876: if (::GetClassInfo(AfxGetInstanceHandle(), szName, &wndcls)) ! 877: { ! 878: // already registered, assert everything is good ! 879: ASSERT(wndcls.style == nClassStyle); ! 880: ASSERT(wndcls.hIcon == hIcon); ! 881: ASSERT(wndcls.hCursor == hCursor); ! 882: ASSERT(wndcls.hbrBackground == hbrBackground); ! 883: return szName; ! 884: } ! 885: ! 886: // otherwise we need to register a new class ! 887: wndcls.style = nClassStyle; ! 888: wndcls.lpfnWndProc = AfxWndProc; ! 889: wndcls.cbClsExtra = wndcls.cbWndExtra = 0; ! 890: wndcls.hInstance = AfxGetInstanceHandle(); ! 891: wndcls.hIcon = hIcon; ! 892: wndcls.hCursor = hCursor; ! 893: wndcls.hbrBackground = hbrBackground; ! 894: wndcls.lpszMenuName = NULL; ! 895: wndcls.lpszClassName = szName; ! 896: if (!::RegisterClass(&wndcls)) ! 897: AfxThrowResourceException(); ! 898: return szName; ! 899: } ! 900: ! 901: ! 902: ! 903: ///////////////////////////////////////////////////////////////////////////// ! 904: // Dialogs have 2-phase construction ! 905: ! 906: IMPLEMENT_DYNAMIC(CDialog, CWnd) ! 907: ! 908: CDialog::CDialog() ! 909: { ! 910: ASSERT(m_hWnd == NULL); ! 911: ! 912: m_hBrushCtlBk = NULL; ! 913: VERIFY(SetCtlBkColor(::GetSysColor(COLOR_BTNFACE))); ! 914: } ! 915: ! 916: CDialog::~CDialog() ! 917: { ! 918: if (m_hBrushCtlBk != NULL) ! 919: ::DeleteObject(m_hBrushCtlBk); ! 920: m_hBrushCtlBk = NULL; ! 921: } ! 922: ! 923: #ifdef _DEBUG ! 924: void ! 925: CDialog::AssertValid() const ! 926: { ! 927: CWnd::AssertValid(); ! 928: ASSERT(m_hWnd != (HWND)1); ! 929: } ! 930: #endif ! 931: ! 932: // Modeless ! 933: BOOL ! 934: CDialog::Create(LPCSTR lpTemplateName, CWnd* pParentWnd) ! 935: { ! 936: if (pParentWnd == NULL) ! 937: pParentWnd = AfxGetApp()->m_pMainWnd; ! 938: ! 939: _AfxHookWindowCreate(this); ! 940: HWND hWnd = ::CreateDialog(AfxGetResourceHandle(), ! 941: lpTemplateName, pParentWnd->GetSafeHwnd(), ! 942: (DLGPROC)_AfxDlgProc); ! 943: _AfxUnhookWindowCreate(); ! 944: ! 945: return (m_hWnd = hWnd) != NULL; ! 946: } ! 947: ! 948: BOOL ! 949: CDialog::CreateIndirect(const void FAR* lpDialogTemplate, ! 950: CWnd* pParentWnd) ! 951: { ! 952: if (pParentWnd == NULL) ! 953: pParentWnd = AfxGetApp()->m_pMainWnd; ! 954: ! 955: _AfxHookWindowCreate(this); ! 956: #ifdef _NTWIN ! 957: HWND hWnd = ::CreateDialogIndirect(AfxGetResourceHandle(), ! 958: (LPDLGTEMPLATE)lpDialogTemplate, pParentWnd->GetSafeHwnd(), ! 959: (DLGPROC)_AfxDlgProc); ! 960: #else ! 961: HWND hWnd = ::CreateDialogIndirect(AfxGetResourceHandle(), ! 962: lpDialogTemplate, pParentWnd->GetSafeHwnd(), ! 963: (DLGPROC)_AfxDlgProc); ! 964: #endif ! 965: _AfxUnhookWindowCreate(); ! 966: ! 967: return (m_hWnd = hWnd) != NULL; ! 968: } ! 969: ! 970: void ! 971: CDialog::OnSetFont(CFont*) ! 972: { ! 973: // ignore it ! 974: } ! 975: ! 976: BOOL ! 977: CDialog::OnInitDialog() ! 978: { ! 979: return TRUE; // set focus to first one ! 980: } ! 981: ! 982: ! 983: BOOL ! 984: CDialog::SetCtlBkColor(COLORREF clrCtlBk) ! 985: { ! 986: if (m_hBrushCtlBk != NULL) ! 987: ::DeleteObject(m_hBrushCtlBk); ! 988: m_hBrushCtlBk = NULL; ! 989: ! 990: if (clrCtlBk == 0xFFFFFFFF) ! 991: { ! 992: // -1 means do not handle any WM_CTLCOLOR messages ! 993: ASSERT(m_hBrushCtlBk == NULL); ! 994: return TRUE; ! 995: } ! 996: ! 997: m_hBrushCtlBk = ::CreateSolidBrush(clrCtlBk); ! 998: return m_hBrushCtlBk != NULL ? TRUE : FALSE; ! 999: } ! 1000: ! 1001: HBRUSH ! 1002: CDialog::OnCtlColor(CDC* pDC, CWnd* /* pWnd */, UINT nCtlColor) ! 1003: { ! 1004: if (m_hBrushCtlBk == NULL || ! 1005: nCtlColor == CTLCOLOR_LISTBOX || ! 1006: nCtlColor == CTLCOLOR_EDIT || ! 1007: nCtlColor == CTLCOLOR_MSGBOX) ! 1008: return (HBRUSH)Default(); ! 1009: ! 1010: // Use new look AFX colors ! 1011: // Set the background color for controls ! 1012: LOGBRUSH logbrush; ! 1013: if (::GetObject(m_hBrushCtlBk, sizeof(LOGBRUSH), (LPSTR)&logbrush) != 0) ! 1014: { ! 1015: pDC->SetBkColor(logbrush.lbColor); ! 1016: } ! 1017: else ! 1018: { ! 1019: TRACE("Warning: couldn't set background color for CTLCOLOR\n"); ! 1020: } ! 1021: return m_hBrushCtlBk; ! 1022: } ! 1023: ! 1024: BEGIN_MESSAGE_MAP(CDialog, CWnd) ! 1025: ON_WM_CTLCOLOR() ! 1026: END_MESSAGE_MAP() ! 1027: ! 1028: ///////////////////////////////////////////////////////////////////////////// ! 1029: // Dialog Proc support ! 1030: ! 1031: BOOL ! 1032: CDialog::PreTranslateMessage(MSG* pMsg) ! 1033: { ! 1034: // for modeless processing (or modal) ! 1035: ASSERT(m_hWnd != NULL); ! 1036: ! 1037: // filter both messages to dialog and from children ! 1038: return ::IsDialogMessage(m_hWnd, pMsg); ! 1039: } ! 1040: ! 1041: WNDPROC* ! 1042: CDialog::GetSuperWndProcAddr() ! 1043: { ! 1044: static WNDPROC pfnSuper; ! 1045: return &pfnSuper; ! 1046: } ! 1047: ! 1048: ///////////////////////////////////////////////////////////////////////////// ! 1049: // CModalDialog ! 1050: ! 1051: IMPLEMENT_DYNAMIC(CModalDialog, CDialog) ! 1052: ! 1053: BEGIN_MESSAGE_MAP(CModalDialog, CDialog) ! 1054: ON_COMMAND(IDOK, OnOK) ! 1055: ON_COMMAND(IDCANCEL, OnCancel) ! 1056: END_MESSAGE_MAP() ! 1057: ! 1058: // Constructors just save parameters ! 1059: CModalDialog::CModalDialog(LPCSTR lpTemplateName, CWnd* pParentWnd) ! 1060: { ! 1061: m_lpDialogTemplate = lpTemplateName; ! 1062: m_hDialogTemplate = NULL; ! 1063: m_pParentWnd = pParentWnd; ! 1064: } ! 1065: ! 1066: CModalDialog::CModalDialog(UINT nIDTemplate, CWnd* pParentWnd) ! 1067: { ! 1068: m_lpDialogTemplate = MAKEINTRESOURCE(nIDTemplate); ! 1069: m_hDialogTemplate = NULL; ! 1070: m_pParentWnd = pParentWnd; ! 1071: } ! 1072: ! 1073: BOOL ! 1074: CModalDialog::CreateIndirect(HANDLE hDialogTemplate) ! 1075: { ! 1076: // must be called on an empty constructed CModalDialog ! 1077: ASSERT(m_lpDialogTemplate == NULL); ! 1078: ASSERT(m_hDialogTemplate == NULL); ! 1079: ! 1080: m_hDialogTemplate = hDialogTemplate; ! 1081: return TRUE; // always ok (DoModal actually brings up dialog) ! 1082: } ! 1083: ! 1084: #ifdef _DEBUG ! 1085: void ! 1086: CModalDialog::AssertValid() const ! 1087: { ! 1088: CDialog::AssertValid(); ! 1089: } ! 1090: ! 1091: void ! 1092: CModalDialog::Dump(CDumpContext& dc) const ! 1093: { ! 1094: CDialog::Dump(dc); ! 1095: dc << "\nm_lpDialogTemplate = " << m_lpDialogTemplate << "\n"; ! 1096: dc << "m_hDialogTemplate = " << m_hDialogTemplate << "\n"; ! 1097: dc << "m_pParentWnd = " << (void *)m_pParentWnd; ! 1098: } ! 1099: #endif ! 1100: ! 1101: int ! 1102: CModalDialog::DoModal() ! 1103: { ! 1104: HWND hWndParent; ! 1105: int nResult; ! 1106: ! 1107: // can be constructed with a resource template or CreateIndirect ! 1108: ASSERT(m_lpDialogTemplate != NULL || m_hDialogTemplate != NULL); ! 1109: ! 1110: // find parent HWND ! 1111: if (m_pParentWnd != NULL) ! 1112: hWndParent = m_pParentWnd->m_hWnd; ! 1113: else ! 1114: hWndParent = AfxGetApp()->m_pMainWnd->GetSafeHwnd(); ! 1115: ! 1116: _AfxHookWindowCreate(this); ! 1117: if (m_lpDialogTemplate != NULL) ! 1118: { ! 1119: nResult = ::DialogBox(AfxGetResourceHandle(), m_lpDialogTemplate, ! 1120: hWndParent, (DLGPROC)_AfxDlgProc); ! 1121: } ! 1122: else ! 1123: { ! 1124: #ifdef _NTWIN ! 1125: nResult = ::DialogBoxIndirect(AfxGetResourceHandle(), ! 1126: (LPDLGTEMPLATE)m_hDialogTemplate, hWndParent, (DLGPROC)_AfxDlgProc); ! 1127: #else ! 1128: nResult = ::DialogBoxIndirect(AfxGetResourceHandle(), m_hDialogTemplate, ! 1129: hWndParent, (DLGPROC)_AfxDlgProc); ! 1130: #endif ! 1131: } ! 1132: ! 1133: _AfxUnhookWindowCreate(); // just in case ! 1134: Detach(); // just in case ! 1135: return nResult; ! 1136: } ! 1137: ! 1138: ///////////////////////////////////////////////////////////////////////////// ! 1139: // Standard CModalDialog implementation ! 1140: ! 1141: void ! 1142: CModalDialog::OnOK() ! 1143: { ! 1144: EndDialog(IDOK); ! 1145: } ! 1146: ! 1147: void ! 1148: CModalDialog::OnCancel() ! 1149: { ! 1150: EndDialog(IDCANCEL); ! 1151: } ! 1152: ! 1153: ///////////////////////////////////////////////////////////////////////////// ! 1154: // CRect for creating windows with the default position/size ! 1155: const CRect NEAR CFrameWnd::rectDefault(CW_USEDEFAULT, CW_USEDEFAULT, ! 1156: 0 /* 2*CW_USEDEFAULT */, 0 /* 2*CW_USEDEFAULT */); ! 1157: ! 1158: // CWnds for setting z-order with SetWindowPos's pWndInsertAfter parameter ! 1159: const CWnd NEAR CWnd::wndTop((HWND)0); ! 1160: const CWnd NEAR CWnd::wndBottom((HWND)1); ! 1161: const CWnd NEAR CWnd::wndTopMost((HWND)-1); ! 1162: const CWnd NEAR CWnd::wndNoTopMost((HWND)-2); ! 1163: ! 1164: ///////////////////////////////////////////////////////////////////////////// ! 1165: // Message table implementation ! 1166: ! 1167: CMessageMap CWnd::messageMap = ! 1168: { ! 1169: NULL, // end of chain of message maps ! 1170: (CMessageEntry FAR*) &CWnd::_messageEntries ! 1171: }; ! 1172: ! 1173: CMessageMap* CWnd::GetMessageMap() const ! 1174: { ! 1175: return &CWnd::messageMap; ! 1176: } ! 1177: ! 1178: ! 1179: CMessageEntry BASED_CODE CWnd::_messageEntries[] = ! 1180: { ! 1181: ON_WM_COMPAREITEM() ! 1182: ON_WM_MEASUREITEM() ! 1183: ON_WM_DRAWITEM() ! 1184: ON_WM_DELETEITEM() ! 1185: ON_WM_CTLCOLOR() ! 1186: ON_WM_DESTROY() ! 1187: ON_WM_NCDESTROY() ! 1188: #ifdef _NTWIN ! 1189: ON_MESSAGE(WM_CTLCOLORMSGBOX, OnNTCtlColor) ! 1190: ON_MESSAGE(WM_CTLCOLOREDIT, OnNTCtlColor) ! 1191: ON_MESSAGE(WM_CTLCOLORLISTBOX, OnNTCtlColor) ! 1192: ON_MESSAGE(WM_CTLCOLORBTN, OnNTCtlColor) ! 1193: ON_MESSAGE(WM_CTLCOLORDLG, OnNTCtlColor) ! 1194: ON_MESSAGE(WM_CTLCOLORSCROLLBAR, OnNTCtlColor) ! 1195: ON_MESSAGE(WM_CTLCOLORSTATIC, OnNTCtlColor) ! 1196: #endif ! 1197: ! 1198: { 0, 0, AfxSig_end, (AFX_PMSG)0 } ! 1199: }; ! 1200: ! 1201: union MessageMapFunctions ! 1202: { ! 1203: AFX_PMSG pfn; // generic member function pointer ! 1204: ! 1205: // specific type safe variants ! 1206: BOOL (CWnd::*pfn_bD)(CDC *); ! 1207: BOOL (CWnd::*pfn_bb)(BOOL); ! 1208: BOOL (CWnd::*pfn_bWww)(CWnd*, UINT, UINT); ! 1209: HBRUSH (CWnd::*pfn_hDWw)(CDC *, CWnd*, UINT); ! 1210: int (CWnd::*pfn_iwWw)(UINT, CWnd*, UINT); ! 1211: int (CWnd::*pfn_iWww)(CWnd*, UINT, UINT); ! 1212: int (CWnd::*pfn_is)(LPSTR); ! 1213: LONG (CWnd::*pfn_lwl)(UINT, LONG); ! 1214: LONG (CWnd::*pfn_lwwM)(UINT, UINT, CMenu *); ! 1215: void (CWnd::*pfn_vv)(void); ! 1216: ! 1217: void (CWnd::*pfn_vw)(UINT); ! 1218: void (CWnd::*pfn_vww)(UINT, UINT); ! 1219: void (CWnd::*pfn_vvii)(int, int); ! 1220: void (CWnd::*pfn_vwww)(UINT, UINT, UINT); ! 1221: void (CWnd::*pfn_vwii)(UINT, int, int); ! 1222: void (CWnd::*pfn_vwl)(UINT, LONG); ! 1223: void (CWnd::*pfn_vbWW)(BOOL, CWnd*, CWnd*); ! 1224: void (CWnd::*pfn_vD)(CDC *); ! 1225: void (CWnd::*pfn_vM)(CMenu *); ! 1226: void (CWnd::*pfn_vMwb)(CMenu *, UINT, BOOL); ! 1227: ! 1228: void (CWnd::*pfn_vW)(CWnd*); ! 1229: void (CWnd::*pfn_vWww)(CWnd*, UINT, UINT); ! 1230: void (CWnd::*pfn_vWh)(CWnd*, HANDLE); ! 1231: void (CWnd::*pfn_vwW)(UINT, CWnd*); ! 1232: void (CWnd::*pfn_vwWb)(UINT, CWnd*, BOOL); ! 1233: void (CWnd::*pfn_vwwW)(UINT, UINT, CWnd*); ! 1234: void (CWnd::*pfn_vs)(LPSTR); ! 1235: UINT (CWnd::*pfn_wp)(CPoint); ! 1236: UINT (CWnd::*pfn_wv)(void); ! 1237: BOOL (CWnd::*pfn_bh)(HANDLE); ! 1238: void (CWnd::*pfn_vPOS)(WINDOWPOS FAR*); ! 1239: void (CWnd::*pfn_vCALC)(NCCALCSIZE_PARAMS FAR*); ! 1240: #ifdef _NTWIN ! 1241: void (CWnd::*pfn_vwp)(UINT, CPoint); ! 1242: void (CWnd::*pfn_vwwh)(UINT, UINT, HANDLE); ! 1243: #endif ! 1244: }; ! 1245: ! 1246: ///////////////////////////////////////////////////////////////////////////// ! 1247: // Routines for fast search of message maps ! 1248: ! 1249: ! 1250: // Hand tuned routine ! 1251: ! 1252: #pragma optimize("qgel", off) // assembler cannot be globally optimized ! 1253: ! 1254: #ifdef _NTWIN ! 1255: // C versions of search routines ! 1256: static inline CMessageEntry FAR* ! 1257: FindMessageEntry(CMessageEntry FAR* lpEntry, UINT nMsg, UINT nID) ! 1258: { ! 1259: while (lpEntry->nSig != AfxSig_end) ! 1260: { ! 1261: if (lpEntry->nMessage == nMsg && lpEntry->nID == nID) ! 1262: return lpEntry; ! 1263: lpEntry++; ! 1264: } ! 1265: return NULL; // not found ! 1266: } ! 1267: ! 1268: #else ! 1269: static CMessageEntry FAR* NEAR ! 1270: FindMessageEntry(CMessageEntry FAR* lpEntry, UINT nMsg, UINT nID) ! 1271: { ! 1272: _asm ! 1273: { ! 1274: LES BX,lpEntry ! 1275: MOV AX,nMsg ! 1276: MOV DX,nID ! 1277: __loop: ! 1278: MOV CX,WORD PTR ES:[BX+4] ; nSig (0 => end) ! 1279: JCXZ __failed ! 1280: CMP AX,WORD PTR ES:[BX] ; nMessage ! 1281: JE __found_1 ! 1282: __next: ! 1283: ADD BX,SIZE CMessageEntry ! 1284: JMP __loop ! 1285: __found_1: ! 1286: CMP DX,WORD PTR ES:[BX+2] ; nID ! 1287: JNE __next ! 1288: // found a match ! 1289: MOV WORD PTR lpEntry,BX ! 1290: MOV WORD PTR lpEntry+2,ES ! 1291: JMP __end ! 1292: __failed: ! 1293: XOR AX,AX ! 1294: MOV WORD PTR lpEntry,AX ! 1295: MOV WORD PTR lpEntry+2,AX ! 1296: __end: ! 1297: } ! 1298: return lpEntry; ! 1299: } ! 1300: #endif //_NTWIN ! 1301: ! 1302: #pragma optimize("", on) // return to default optimizations ! 1303: ! 1304: ! 1305: ///////////////////////////////////////////////////////////////////////////// ! 1306: ! 1307: #ifndef iHashMax ! 1308: // iHashMax must be a power of two ! 1309: #ifdef _NEARDATA ! 1310: #define iHashMax 64 ! 1311: #else ! 1312: #define iHashMax 256 ! 1313: #endif ! 1314: #endif ! 1315: ! 1316: struct MsgCache ! 1317: { ! 1318: UINT nMsg; ! 1319: CMessageEntry FAR* lpEntry; ! 1320: CMessageMap* pMessageMap; ! 1321: }; ! 1322: ! 1323: MsgCache _afxMsgCache[iHashMax]; ! 1324: ! 1325: LONG ! 1326: CWnd::WindowProc(UINT nMsg, UINT wParam, LONG lParam) ! 1327: { ! 1328: register CMessageMap* pMessageMap; ! 1329: CMessageEntry FAR* lpEntry; ! 1330: ! 1331: if (nMsg == WM_COMMAND) // special case for commands ! 1332: { ! 1333: if (OnCommand(wParam, lParam)) ! 1334: return 1L; // command handled ! 1335: else ! 1336: return (LONG)DefWindowProc(nMsg, wParam, lParam); // call default handler ! 1337: } ! 1338: ! 1339: pMessageMap = GetMessageMap(); ! 1340: UINT iHash = (_AFX_FP_OFF(pMessageMap) ^ nMsg) & (iHashMax-1); ! 1341: MsgCache& msgCache = _afxMsgCache[iHash]; ! 1342: ! 1343: if (nMsg == msgCache.nMsg && pMessageMap == msgCache.pMessageMap) ! 1344: { ! 1345: // Cache hit ! 1346: lpEntry = msgCache.lpEntry; ! 1347: if (lpEntry == NULL) ! 1348: return (LONG)DefWindowProc(nMsg, wParam, lParam); ! 1349: else if (nMsg < 0xC000) ! 1350: goto LDispatch; ! 1351: else ! 1352: goto LDispatchRegistered; ! 1353: } ! 1354: else ! 1355: { ! 1356: // not in cache, look for it ! 1357: msgCache.nMsg = nMsg; ! 1358: msgCache.pMessageMap = pMessageMap; ! 1359: ! 1360: for (/* pMessageMap already init'ed */; pMessageMap != NULL; ! 1361: pMessageMap = pMessageMap->pBaseMessageMap) ! 1362: { ! 1363: // This may loop forever if the message maps are not properly ! 1364: // chained together. Make sure each window class's message map ! 1365: // points to the base window class's message map. ! 1366: ! 1367: if (nMsg < 0xC000) ! 1368: { ! 1369: // constant window message ! 1370: if ((lpEntry = FindMessageEntry(pMessageMap->lpEntries, ! 1371: nMsg, 0)) != NULL) ! 1372: { ! 1373: msgCache.lpEntry = lpEntry; ! 1374: goto LDispatch; ! 1375: } ! 1376: } ! 1377: else ! 1378: { ! 1379: // registered windows message ! 1380: lpEntry = pMessageMap->lpEntries; ! 1381: ! 1382: while ((lpEntry = FindMessageEntry(lpEntry, 0xC000, 0)) != NULL) ! 1383: { ! 1384: UINT NEAR* pnID = (UINT NEAR*)(lpEntry->nSig); ! 1385: ASSERT(*pnID >= 0xC000); ! 1386: // must be successfully registered ! 1387: if (*pnID == nMsg) ! 1388: { ! 1389: msgCache.lpEntry = lpEntry; ! 1390: goto LDispatchRegistered; ! 1391: } ! 1392: lpEntry++; // keep looking past this one ! 1393: } ! 1394: } ! 1395: } ! 1396: ! 1397: msgCache.lpEntry = NULL; ! 1398: return DefWindowProc(nMsg, wParam, lParam); ! 1399: } ! 1400: ASSERT(FALSE); // not reached ! 1401: ! 1402: ! 1403: LDispatch: ! 1404: ASSERT(nMsg < 0xC000); ! 1405: union MessageMapFunctions mmf; ! 1406: mmf.pfn = lpEntry->pfn; ! 1407: ! 1408: switch (lpEntry->nSig) ! 1409: { ! 1410: default: ! 1411: ASSERT(FALSE); ! 1412: return 0; ! 1413: ! 1414: case AfxSig_bD: ! 1415: return (this->*mmf.pfn_bD)(CDC::FromHandle((HDC)wParam)); ! 1416: ! 1417: case AfxSig_bb: ! 1418: return (this->*mmf.pfn_bb)((BOOL)wParam); ! 1419: ! 1420: case AfxSig_bWww: ! 1421: return (this->*mmf.pfn_bWww)(CWnd::FromHandle((HWND)wParam), ! 1422: LOWORD(lParam), HIWORD(lParam)); ! 1423: ! 1424: #ifdef _NTWIN ! 1425: case AfxSig_hDWw: ! 1426: { ! 1427: ASSERT(nMsg == WM_CTLCOLOR); ! 1428: struct _AFXCTLCOLOR* pCtl = (struct _AFXCTLCOLOR*)lParam; ! 1429: return (LONG)((this->*mmf.pfn_hDWw)( CDC::FromHandle(pCtl->hDC), ! 1430: CWnd::FromHandle(pCtl->hWnd), pCtl->nCtlType)); ! 1431: } ! 1432: #else ! 1433: case AfxSig_hDWw: ! 1434: return (LONG)(UINT)(this->*mmf.pfn_hDWw)(CDC::FromHandle((HDC)wParam), ! 1435: CWnd::FromHandle((HWND)LOWORD(lParam)), HIWORD(lParam)); ! 1436: #endif ! 1437: ! 1438: #ifndef _NTWIN ! 1439: case AfxSig_iwWw: ! 1440: return (this->*mmf.pfn_iwWw)(wParam, CWnd::FromHandle((HWND)LOWORD(lParam)), ! 1441: HIWORD(lParam)); ! 1442: #else ! 1443: case AfxSig_iwWw: ! 1444: return (this->*mmf.pfn_iwWw)(LOWORD(wParam), ! 1445: CWnd::FromHandle((HWND)lParam), ! 1446: HIWORD(wParam)); ! 1447: #endif ! 1448: ! 1449: case AfxSig_iWww: ! 1450: return (this->*mmf.pfn_iWww)(CWnd::FromHandle((HWND)wParam), ! 1451: LOWORD(lParam), HIWORD(lParam)); ! 1452: ! 1453: case AfxSig_is: ! 1454: return (this->*mmf.pfn_is)((LPSTR)lParam); ! 1455: ! 1456: case AfxSig_lwl: ! 1457: return (this->*mmf.pfn_lwl)(wParam, lParam); ! 1458: ! 1459: #ifndef _NTWIN ! 1460: case AfxSig_lwwM: ! 1461: return (this->*mmf.pfn_lwwM)(wParam, LOWORD(lParam), ! 1462: CMenu::FromHandle((HMENU)HIWORD(lParam))); ! 1463: #else ! 1464: case AfxSig_lwwM: ! 1465: return (this->*mmf.pfn_lwwM)((UINT)LOWORD(wParam), (UINT)HIWORD(wParam), ! 1466: (CMenu*)CMenu::FromHandle((HMENU)lParam)); ! 1467: #endif ! 1468: ! 1469: case AfxSig_vv: ! 1470: (this->*mmf.pfn_vv)(); ! 1471: return 0; ! 1472: ! 1473: ! 1474: case AfxSig_vw: // AfxSig_vb: ! 1475: (this->*mmf.pfn_vw)(wParam); ! 1476: return 0; ! 1477: ! 1478: case AfxSig_vww: ! 1479: #ifndef _NTWIN ! 1480: (this->*mmf.pfn_vww)(wParam, LOWORD(lParam)); ! 1481: #else ! 1482: (this->*mmf.pfn_vww)(wParam, lParam); ! 1483: #endif ! 1484: return 0; ! 1485: ! 1486: case AfxSig_vvii: ! 1487: (this->*mmf.pfn_vvii)(LOWORD(lParam), HIWORD(lParam)); ! 1488: return 0; ! 1489: ! 1490: #ifdef _NTWIN ! 1491: case AfxSig_vwwh: ! 1492: (this->*mmf.pfn_vwwh)(LOWORD(wParam), HIWORD(wParam), (HANDLE)lParam); ! 1493: return 0; ! 1494: #endif ! 1495: ! 1496: case AfxSig_vwww: ! 1497: (this->*mmf.pfn_vwww)(wParam, LOWORD(lParam), HIWORD(lParam)); ! 1498: return 0; ! 1499: ! 1500: case AfxSig_vwii: ! 1501: (this->*mmf.pfn_vwii)(wParam, LOWORD(lParam), HIWORD(lParam)); ! 1502: return 0; ! 1503: ! 1504: case AfxSig_vwl: ! 1505: (this->*mmf.pfn_vwl)(wParam, lParam); ! 1506: return 0; ! 1507: ! 1508: #ifndef _NTWIN ! 1509: case AfxSig_vbWW: ! 1510: (this->*mmf.pfn_vbWW)((BOOL)wParam, ! 1511: CWnd::FromHandle((HWND)LOWORD(lParam)), ! 1512: CWnd::FromHandle((HWND)HIWORD(lParam))); ! 1513: return 0; ! 1514: #else ! 1515: case AfxSig_vbWW: ! 1516: (this->*mmf.pfn_vbWW)(m_hWnd == (HWND)lParam, ! 1517: CWnd::FromHandle((HWND)lParam), ! 1518: CWnd::FromHandle((HWND)wParam)); ! 1519: return 0; ! 1520: #endif ! 1521: ! 1522: case AfxSig_vD: ! 1523: (this->*mmf.pfn_vD)(CDC::FromHandle((HDC)wParam)); ! 1524: return 0; ! 1525: ! 1526: case AfxSig_vM: ! 1527: (this->*mmf.pfn_vM)(CMenu::FromHandle((HMENU)wParam)); ! 1528: return 0; ! 1529: ! 1530: case AfxSig_vMwb: ! 1531: (this->*mmf.pfn_vMwb)(CMenu::FromHandle((HMENU)wParam), ! 1532: LOWORD(lParam), (BOOL)HIWORD(lParam)); ! 1533: return 0; ! 1534: ! 1535: ! 1536: case AfxSig_vW: ! 1537: (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)wParam)); ! 1538: return 0; ! 1539: ! 1540: case AfxSig_vWww: ! 1541: (this->*mmf.pfn_vWww)(CWnd::FromHandle((HWND)wParam), LOWORD(lParam), ! 1542: HIWORD(lParam)); ! 1543: return 0; ! 1544: ! 1545: #ifndef _NTWIN ! 1546: case AfxSig_vWh: ! 1547: (this->*mmf.pfn_vWh)(CWnd::FromHandle((HWND)wParam), ! 1548: (HANDLE)LOWORD(lParam)); ! 1549: return 0; ! 1550: #else ! 1551: case AfxSig_vWh: ! 1552: (this->*mmf.pfn_vWh)(CWnd::FromHandle((HWND)wParam), ! 1553: (HANDLE)lParam); ! 1554: return 0; ! 1555: #endif ! 1556: ! 1557: #ifndef _NTWIN ! 1558: case AfxSig_vwW: ! 1559: (this->*mmf.pfn_vwW)(wParam, CWnd::FromHandle((HWND)LOWORD(lParam))); ! 1560: return 0; ! 1561: #else ! 1562: case AfxSig_vwW: ! 1563: (this->*mmf.pfn_vwW)(wParam, CWnd::FromHandle((HWND)lParam)); ! 1564: return 0; ! 1565: #endif ! 1566: ! 1567: #ifndef _NTWIN ! 1568: case AfxSig_vwWb: ! 1569: (this->*mmf.pfn_vwWb)(wParam, CWnd::FromHandle((HWND)LOWORD(lParam)), ! 1570: (BOOL)HIWORD(lParam)); ! 1571: return 0; ! 1572: #else ! 1573: case AfxSig_vwWb: ! 1574: (this->*mmf.pfn_vwWb)((UINT)(LOWORD(wParam)), ! 1575: CWnd::FromHandle((HWND)lParam), ! 1576: (BOOL)(!(!(HIWORD(wParam))))); ! 1577: return 0; ! 1578: #endif //_NTWIN ! 1579: ! 1580: #ifndef _NTWIN ! 1581: case AfxSig_vwwW: ! 1582: (this->*mmf.pfn_vwwW)(wParam, LOWORD(lParam), ! 1583: CWnd::FromHandle((HWND)HIWORD(lParam))); ! 1584: return 0; ! 1585: #else ! 1586: case AfxSig_vwwW: ! 1587: (this->*mmf.pfn_vwwW)(LOWORD(wParam), HIWORD(wParam), ! 1588: CWnd::FromHandle((HWND)lParam)); ! 1589: return 0; ! 1590: #endif ! 1591: ! 1592: case AfxSig_vs: ! 1593: (this->*mmf.pfn_vs)((LPSTR)lParam); ! 1594: return 0; ! 1595: ! 1596: #ifndef _NTWIN ! 1597: case AfxSig_wp: ! 1598: return (this->*mmf.pfn_wp)(*(CPoint*)&lParam); ! 1599: #else ! 1600: case AfxSig_wp: ! 1601: { ! 1602: CPoint point((DWORD)lParam); ! 1603: return (this->*mmf.pfn_wp)(point); ! 1604: } ! 1605: ! 1606: case AfxSig_vwp: ! 1607: { ! 1608: CPoint point((DWORD)lParam); ! 1609: (this->*mmf.pfn_vwp)(wParam, point); ! 1610: return 0; ! 1611: } ! 1612: #endif ! 1613: ! 1614: case AfxSig_wv: // AfxSig_bv, AfxSig_wv ! 1615: return (this->*mmf.pfn_wv)(); ! 1616: ! 1617: case AfxSig_bh: ! 1618: return (this->*mmf.pfn_bh)((HANDLE)wParam); ! 1619: ! 1620: case AfxSig_vCALC: ! 1621: (this->*mmf.pfn_vCALC)((NCCALCSIZE_PARAMS FAR*)lParam); ! 1622: return 0; ! 1623: ! 1624: case AfxSig_vPOS: ! 1625: (this->*mmf.pfn_vPOS)((WINDOWPOS FAR*)lParam); ! 1626: return 0; ! 1627: } ! 1628: ASSERT(FALSE); // not reached ! 1629: ! 1630: LDispatchRegistered: // for registered windows messages ! 1631: ASSERT(nMsg >= 0xC000); ! 1632: mmf.pfn = lpEntry->pfn; ! 1633: return (this->*mmf.pfn_lwl)(wParam, lParam); ! 1634: } ! 1635: ! 1636: BOOL CWnd::OnCommand(UINT wParam, LONG lParam) ! 1637: { ! 1638: #ifdef _NTWIN ! 1639: UINT nID = LOWORD(wParam); ! 1640: HWND hWndCtrl = (HWND)lParam; ! 1641: UINT nNotifyCode = HIWORD(wParam); // control specific ! 1642: #else ! 1643: UINT nID = wParam; ! 1644: HWND hWndCtrl = (HWND)LOWORD(lParam); ! 1645: UINT nNotifyCode = HIWORD(lParam); // control specific ! 1646: #endif ! 1647: if (nID == 0) ! 1648: return FALSE; // 0 control IDs are not allowed ! ! 1649: ! 1650: // default routing for command messages (through closure table) ! 1651: if (hWndCtrl == NULL) ! 1652: nNotifyCode = 0; // accelerators are not special ! 1653: ! 1654: // check in message map table for matching control ID ! 1655: register CMessageMap* pMessageMap; ! 1656: register CMessageEntry FAR* lpEntry; ! 1657: ! 1658: for (pMessageMap = GetMessageMap(); pMessageMap != NULL; ! 1659: pMessageMap = pMessageMap->pBaseMessageMap) ! 1660: { ! 1661: if ((lpEntry = FindMessageEntry(pMessageMap->lpEntries, ! 1662: nNotifyCode, nID)) != NULL) ! 1663: { ! 1664: #ifdef _DEBUG ! 1665: // diagnostic trace reporting of command notifications ! 1666: if (afxTraceFlags & 8) // if command reporting ! 1667: { ! 1668: if (nNotifyCode == 0) ! 1669: { ! 1670: TRACE("SENDING command %d to %s window\n", nID, ! 1671: GetRuntimeClass()->m_pszClassName); ! 1672: } ! 1673: else if (afxTraceFlags & 4) // if verbose windows messages ! 1674: { ! 1675: TRACE("SENDING control notification %d from control id %d " ! 1676: "to %s window\n", nNotifyCode, nID, ! 1677: GetRuntimeClass()->m_pszClassName); ! 1678: } ! 1679: } ! 1680: #endif ! 1681: // dispatch it ! 1682: (this->*lpEntry->pfn)(); ! 1683: return TRUE; // handled ! 1684: } ! 1685: } ! 1686: ! 1687: #ifdef _DEBUG ! 1688: if (afxTraceFlags & 8) ! 1689: { ! 1690: if (nNotifyCode == 0) ! 1691: { ! 1692: TRACE("IGNORING command %d sent to %s window\n", nID, ! 1693: GetRuntimeClass()->m_pszClassName); ! 1694: } ! 1695: else if (afxTraceFlags & 4) // if verbose windows messages ! 1696: { ! 1697: TRACE("IGNORING control notification %d from control id %d " ! 1698: "to %s window\n", nNotifyCode, nID, ! 1699: GetRuntimeClass()->m_pszClassName); ! 1700: } ! 1701: } ! 1702: #endif ! 1703: ! 1704: return FALSE; // not handled ! 1705: } ! 1706: ! 1707: ! 1708: ! 1709: /////////////////////////////////////////////////////////////////////////////
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.