|
|
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.