|
|
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)
1.1.1.2 ! root 537: #ifndef _NTWIN
1.1 root 538: dc << "\nid = " << ::GetWindowWord(m_hWnd, GWW_ID);
1.1.1.2 ! root 539: #else
! 540: dc << "\nid = " << ::GetWindowLong(m_hWnd, GWL_ID);
! 541: #endif
1.1 root 542: }
543: }
544: #endif
545:
546: BOOL
547: CWnd::DestroyWindow()
548: {
549: if (m_hWnd == NULL)
550: return FALSE;
551:
552: void* p;
553: BOOL bInPermanentMap = hWndMap.LookupPermanent(m_hWnd, p);
554: BOOL bRet = ::DestroyWindow(m_hWnd);
555: // Note that 'this' may have been deleted at this point.
556: if (bInPermanentMap)
557: {
558: // Should have been detached by OnNcDestroy
559: ASSERT(!hWndMap.LookupPermanent(m_hWnd, p));
560: }
561: else
562: {
563: // Detach after DestroyWindow called just in case
564: Detach();
565: }
566: return bRet;
567: }
568:
569: /////////////////////////////////////////////////////////////////////////////
570: // Default CWnd implementation
571:
572: LONG CWnd::DefWindowProc(UINT nMsg, UINT wParam, LONG lParam)
573: {
574: WNDPROC pfnWndProc;
575:
576: if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL)
577: return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam);
578: else
579: #ifdef STRICT
580: return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam);
581: #else
582: return ::CallWindowProc((FARPROC)pfnWndProc, m_hWnd, nMsg, wParam, lParam);
583: #endif
584: }
585:
586: WNDPROC* CWnd::GetSuperWndProcAddr()
587: {
588: static WNDPROC pfnSuper = NULL;
589: ASSERT(pfnSuper == NULL); // should never be changed !!!
590: // if this is non-NULL, then a derived class of CWnd
591: // forgot to override 'superWndProc' as well as 'className'
592: return &pfnSuper;
593: }
594:
595: BOOL CWnd::PreTranslateMessage(MSG*)
596: {
597: // no default processing
598: return FALSE;
599: }
600:
601: /////////////////////////////////////////////////////////////////////////////
602: // CWnd will delegate owner draw messages to self drawing controls
603:
604: // Drawing: for all 4 control types
605: void CWnd::OnDrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
606: {
607: UINT nType;
608: if ((nType = lpDrawItemStruct->CtlType) == ODT_MENU)
609: {
610: CMenu* pMenu = CMenu::FromHandle((HMENU)lpDrawItemStruct->hwndItem);
611: if (pMenu != NULL)
612: {
613: pMenu->DrawItem(lpDrawItemStruct);
614: return;
615: }
616: }
617: else
618: {
619: CWnd* pChild = CWnd::FromHandlePermanent(lpDrawItemStruct->hwndItem);
620: if (pChild != NULL)
621: {
622: if (nType == ODT_BUTTON &&
623: pChild->IsKindOf(RUNTIME_CLASS(CButton)))
624: {
625: ((CButton*)pChild)->DrawItem(lpDrawItemStruct);
626: return;
627: }
628: else if (nType == ODT_LISTBOX &&
629: pChild->IsKindOf(RUNTIME_CLASS(CListBox)))
630: {
631: ((CListBox*)pChild)->DrawItem(lpDrawItemStruct);
632: return;
633: }
634: else if (nType == ODT_COMBOBOX &&
635: pChild->IsKindOf(RUNTIME_CLASS(CComboBox)))
636: {
637: ((CComboBox*)pChild)->DrawItem(lpDrawItemStruct);
638: return;
639: }
640: }
641: }
642: // not handled - do default
643: Default();
644: }
645:
646: // Drawing: for all 4 control types
647: int CWnd::OnCompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
648: {
649: CWnd* pChild = CWnd::FromHandlePermanent(lpCompareItemStruct->hwndItem);
650: if (pChild != NULL)
651: {
652: UINT nType = lpCompareItemStruct->CtlType;
653: if (nType == ODT_LISTBOX &&
654: pChild->IsKindOf(RUNTIME_CLASS(CListBox)))
655: {
656: return ((CListBox*)pChild)->CompareItem(lpCompareItemStruct);
657: }
658: else if (nType == ODT_COMBOBOX &&
659: pChild->IsKindOf(RUNTIME_CLASS(CComboBox)))
660: {
661: return ((CComboBox*)pChild)->CompareItem(lpCompareItemStruct);
662: }
663: }
664: // not handled - do default
665: return (int)Default();
666: }
667:
668: void CWnd::OnDeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct)
669: {
670: CWnd* pChild = CWnd::FromHandlePermanent(lpDeleteItemStruct->hwndItem);
671: if (pChild != NULL)
672: {
673: UINT nType = lpDeleteItemStruct->CtlType;
674: if (nType == ODT_LISTBOX &&
675: pChild->IsKindOf(RUNTIME_CLASS(CListBox)))
676: {
677: ((CListBox*)pChild)->DeleteItem(lpDeleteItemStruct);
678: return;
679: }
680: else if (nType == ODT_COMBOBOX &&
681: pChild->IsKindOf(RUNTIME_CLASS(CComboBox)))
682: {
683: ((CComboBox*)pChild)->DeleteItem(lpDeleteItemStruct);
684: return;
685: }
686: }
687: // not handled - do default
688: Default();
689: }
690:
691:
692: static CMenu* FindPopupMenuFromID(CMenu* pMenu, UINT nID)
693: {
694: // walk through all items, looking for ID match
695: UINT nItems = pMenu->GetMenuItemCount();
696: for (int iItem = 0; iItem < (int)nItems; iItem++)
697: {
1.1.1.2 ! root 698: #ifndef _NTWIN
1.1 root 699: if (pMenu->GetMenuState(iItem, MF_BYPOSITION) & MF_POPUP)
1.1.1.2 ! root 700: #else
! 701: //REVIEW_NT: nt bug? not returning MF_POPUP for popup items!
! 702: if (HIBYTE(HIWORD(pMenu->GetMenuState(iItem, MF_BYPOSITION))) != 0)
! 703: #endif
1.1 root 704: {
705: // recurse to child popup
706: CMenu* pPopup = FindPopupMenuFromID(pMenu->GetSubMenu(iItem), nID);
707: // try recursing
708: if (pPopup != NULL)
709: return pPopup;
710: }
711: else if (pMenu->GetMenuItemID(iItem) == nID)
712: {
713: // it is a normal item inside our popup
714: return pMenu;
715: }
716: }
717: // not found
718: return NULL;
719: }
720:
721: // Measure item implementation relies on unique control/menu IDs
722: void CWnd::OnMeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
723: {
724: UINT nType;
725: if ((nType = lpMeasureItemStruct->CtlType) == ODT_MENU)
726: {
727: ASSERT(lpMeasureItemStruct->CtlID == 0);
728: CMenu* pMenu = FindPopupMenuFromID(GetMenu(),
729: lpMeasureItemStruct->itemID);
730: if (pMenu != NULL)
731: {
732: pMenu->MeasureItem(lpMeasureItemStruct);
733: return;
734: }
735: else
736: {
737: TRACE("Warning: unknown WM_MEASUREITEM request for"
738: " menu item 0x%04X\n", lpMeasureItemStruct->itemID);
739: }
740: }
741: else
742: {
743: HWND hWndChild = ::GetDlgItem(m_hWnd, lpMeasureItemStruct->CtlID);
744: CWnd* pChild;
745: if (hWndChild != NULL &&
746: (pChild = CWnd::FromHandlePermanent(hWndChild)) != NULL)
747: {
748: if (nType == ODT_LISTBOX &&
749: pChild->IsKindOf(RUNTIME_CLASS(CListBox)))
750: {
751: ((CListBox*)pChild)->MeasureItem(lpMeasureItemStruct);
752: return;
753: }
754: else if (nType == ODT_COMBOBOX &&
755: pChild->IsKindOf(RUNTIME_CLASS(CComboBox)))
756: {
757: ((CComboBox*)pChild)->MeasureItem(lpMeasureItemStruct);
758: return;
759: }
760: }
761: }
762: // not handled - do default
763: Default();
764: }
765:
766: /////////////////////////////////////////////////////////////////////////////
767: // CFrameWnd
768:
769: IMPLEMENT_DYNAMIC(CFrameWnd, CWnd)
770:
771: CFrameWnd::CFrameWnd()
772: {
773: ASSERT(m_hWnd == NULL);
774: m_hAccelTable = NULL;
775: }
776:
777: CFrameWnd::~CFrameWnd()
778: {
779: if (m_hAccelTable != NULL)
780: ::FreeResource(m_hAccelTable);
781: }
782:
783: void CFrameWnd::PostNcDestroy()
784: {
785: // default for frame windows is to allocate them on the heap
786: // the default post-cleanup is to 'delete this'.
787: // never explicitly call 'delete' on a CFrameWnd, use DestroyWindow instead
788: delete this;
789: }
790:
791: #ifdef _DEBUG
792: void CFrameWnd::AssertValid() const
793: {
794: CWnd::AssertValid();
795: }
796:
797: void CFrameWnd::Dump(CDumpContext& dc) const
798: {
799: CWnd::Dump(dc);
800: dc << "\nm_hAccelTable = " << (UINT) m_hAccelTable;
801: }
802: #endif
803:
804: BOOL CFrameWnd::LoadAccelTable(LPCSTR lpAccelTableName)
805: {
806: ASSERT(m_hAccelTable == NULL); // only do once
807: ASSERT(lpAccelTableName != NULL);
808:
809: m_hAccelTable = ::LoadAccelerators(AfxGetResourceHandle(),
810: lpAccelTableName);
811: return (m_hAccelTable != NULL);
812: }
813:
814: /////////////////////////////////////////////////////////////////////////////
815: // Creation and window tree access
816:
817: BOOL CFrameWnd::Create(LPCSTR lpClassName,
818: LPCSTR lpWindowName,
819: DWORD dwStyle, const RECT& rect,
820: const CWnd* pParentWnd,
821: LPCSTR lpMenuName)
822: {
823: HMENU hMenu = NULL;
824:
825: if (lpClassName == NULL)
826: lpClassName = _afxFrameWnd;
827:
828: if (lpMenuName != NULL)
829: {
830: // load in a menu that will get destroyed when window gets destroyed
831: hMenu = ::LoadMenu(AfxGetResourceHandle(), lpMenuName);
832: if (hMenu == NULL)
833: {
834: TRACE("Warning: failed to load menu for CFrameWnd\n");
835: return FALSE;
836: }
837: }
838:
839: if (!CreateEx(0L, lpClassName, lpWindowName, dwStyle,
840: rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
841: pParentWnd->GetSafeHwnd(), hMenu))
842: {
843: TRACE("Warning: failed to create CFrameWnd\n");
844: return FALSE;
845: }
846: return TRUE;
847: }
848:
849: CFrameWnd* CFrameWnd::GetChildFrame()
850: {
851: return this;
852: }
853:
854: CFrameWnd* CFrameWnd::GetParentFrame()
855: {
856: return this;
857: }
858:
859: BOOL CFrameWnd::PreTranslateMessage(MSG* pMsg)
860: {
861: return (m_hAccelTable != NULL &&
862: ::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg));
863: }
864:
865:
866: /////////////////////////////////////////////////////////////////////////////
867: // Additional helpers for WNDCLASS init
868:
869: const char* AfxRegisterWndClass(UINT nClassStyle,
870: HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon)
871: {
872: // Returns a temporary string name for the class
873: // Save in a CString if you want to use it for a long time
874: WNDCLASS wndcls;
875: static char szName[64]; // 1 global string
876:
877: // generate a synthetic name for this class
878: if (hCursor == NULL && hbrBackground == NULL && hIcon == NULL)
879: wsprintf(szName, "Afx:%x", nClassStyle);
880: else
881: wsprintf(szName, "Afx:%x:%x:%x:%x", nClassStyle,
882: (UINT) hCursor, (UINT) hbrBackground, (UINT) hIcon);
883:
884: // see if the class already exists
885: if (::GetClassInfo(AfxGetInstanceHandle(), szName, &wndcls))
886: {
887: // already registered, assert everything is good
888: ASSERT(wndcls.style == nClassStyle);
889: ASSERT(wndcls.hIcon == hIcon);
890: ASSERT(wndcls.hCursor == hCursor);
891: ASSERT(wndcls.hbrBackground == hbrBackground);
892: return szName;
893: }
894:
895: // otherwise we need to register a new class
896: wndcls.style = nClassStyle;
897: wndcls.lpfnWndProc = AfxWndProc;
898: wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
899: wndcls.hInstance = AfxGetInstanceHandle();
900: wndcls.hIcon = hIcon;
901: wndcls.hCursor = hCursor;
902: wndcls.hbrBackground = hbrBackground;
903: wndcls.lpszMenuName = NULL;
904: wndcls.lpszClassName = szName;
905: if (!::RegisterClass(&wndcls))
906: AfxThrowResourceException();
907: return szName;
908: }
909:
910:
911:
912: /////////////////////////////////////////////////////////////////////////////
913: // Dialogs have 2-phase construction
914:
915: IMPLEMENT_DYNAMIC(CDialog, CWnd)
916:
917: CDialog::CDialog()
918: {
919: ASSERT(m_hWnd == NULL);
920:
921: m_hBrushCtlBk = NULL;
922: VERIFY(SetCtlBkColor(::GetSysColor(COLOR_BTNFACE)));
923: }
924:
925: CDialog::~CDialog()
926: {
927: if (m_hBrushCtlBk != NULL)
928: ::DeleteObject(m_hBrushCtlBk);
929: m_hBrushCtlBk = NULL;
930: }
931:
932: #ifdef _DEBUG
933: void
934: CDialog::AssertValid() const
935: {
936: CWnd::AssertValid();
937: ASSERT(m_hWnd != (HWND)1);
938: }
939: #endif
940:
941: // Modeless
942: BOOL
943: CDialog::Create(LPCSTR lpTemplateName, CWnd* pParentWnd)
944: {
945: if (pParentWnd == NULL)
946: pParentWnd = AfxGetApp()->m_pMainWnd;
947:
948: _AfxHookWindowCreate(this);
949: HWND hWnd = ::CreateDialog(AfxGetResourceHandle(),
950: lpTemplateName, pParentWnd->GetSafeHwnd(),
951: (DLGPROC)_AfxDlgProc);
952: _AfxUnhookWindowCreate();
953:
954: return (m_hWnd = hWnd) != NULL;
955: }
956:
957: BOOL
958: CDialog::CreateIndirect(const void FAR* lpDialogTemplate,
959: CWnd* pParentWnd)
960: {
961: if (pParentWnd == NULL)
962: pParentWnd = AfxGetApp()->m_pMainWnd;
963:
964: _AfxHookWindowCreate(this);
965: #ifdef _NTWIN
966: HWND hWnd = ::CreateDialogIndirect(AfxGetResourceHandle(),
967: (LPDLGTEMPLATE)lpDialogTemplate, pParentWnd->GetSafeHwnd(),
968: (DLGPROC)_AfxDlgProc);
969: #else
970: HWND hWnd = ::CreateDialogIndirect(AfxGetResourceHandle(),
971: lpDialogTemplate, pParentWnd->GetSafeHwnd(),
972: (DLGPROC)_AfxDlgProc);
973: #endif
974: _AfxUnhookWindowCreate();
975:
976: return (m_hWnd = hWnd) != NULL;
977: }
978:
979: void
980: CDialog::OnSetFont(CFont*)
981: {
982: // ignore it
983: }
984:
985: BOOL
986: CDialog::OnInitDialog()
987: {
988: return TRUE; // set focus to first one
989: }
990:
991:
992: BOOL
993: CDialog::SetCtlBkColor(COLORREF clrCtlBk)
994: {
995: if (m_hBrushCtlBk != NULL)
996: ::DeleteObject(m_hBrushCtlBk);
997: m_hBrushCtlBk = NULL;
998:
999: if (clrCtlBk == 0xFFFFFFFF)
1000: {
1001: // -1 means do not handle any WM_CTLCOLOR messages
1002: ASSERT(m_hBrushCtlBk == NULL);
1003: return TRUE;
1004: }
1005:
1006: m_hBrushCtlBk = ::CreateSolidBrush(clrCtlBk);
1007: return m_hBrushCtlBk != NULL ? TRUE : FALSE;
1008: }
1009:
1010: HBRUSH
1011: CDialog::OnCtlColor(CDC* pDC, CWnd* /* pWnd */, UINT nCtlColor)
1012: {
1013: if (m_hBrushCtlBk == NULL ||
1014: nCtlColor == CTLCOLOR_LISTBOX ||
1015: nCtlColor == CTLCOLOR_EDIT ||
1016: nCtlColor == CTLCOLOR_MSGBOX)
1017: return (HBRUSH)Default();
1018:
1019: // Use new look AFX colors
1020: // Set the background color for controls
1021: LOGBRUSH logbrush;
1022: if (::GetObject(m_hBrushCtlBk, sizeof(LOGBRUSH), (LPSTR)&logbrush) != 0)
1023: {
1024: pDC->SetBkColor(logbrush.lbColor);
1025: }
1026: else
1027: {
1028: TRACE("Warning: couldn't set background color for CTLCOLOR\n");
1029: }
1030: return m_hBrushCtlBk;
1031: }
1032:
1033: BEGIN_MESSAGE_MAP(CDialog, CWnd)
1034: ON_WM_CTLCOLOR()
1035: END_MESSAGE_MAP()
1036:
1037: /////////////////////////////////////////////////////////////////////////////
1038: // Dialog Proc support
1039:
1040: BOOL
1041: CDialog::PreTranslateMessage(MSG* pMsg)
1042: {
1043: // for modeless processing (or modal)
1044: ASSERT(m_hWnd != NULL);
1045:
1046: // filter both messages to dialog and from children
1047: return ::IsDialogMessage(m_hWnd, pMsg);
1048: }
1049:
1050: WNDPROC*
1051: CDialog::GetSuperWndProcAddr()
1052: {
1053: static WNDPROC pfnSuper;
1054: return &pfnSuper;
1055: }
1056:
1057: /////////////////////////////////////////////////////////////////////////////
1058: // CModalDialog
1059:
1060: IMPLEMENT_DYNAMIC(CModalDialog, CDialog)
1061:
1062: BEGIN_MESSAGE_MAP(CModalDialog, CDialog)
1063: ON_COMMAND(IDOK, OnOK)
1064: ON_COMMAND(IDCANCEL, OnCancel)
1065: END_MESSAGE_MAP()
1066:
1067: // Constructors just save parameters
1068: CModalDialog::CModalDialog(LPCSTR lpTemplateName, CWnd* pParentWnd)
1069: {
1070: m_lpDialogTemplate = lpTemplateName;
1071: m_hDialogTemplate = NULL;
1072: m_pParentWnd = pParentWnd;
1073: }
1074:
1075: CModalDialog::CModalDialog(UINT nIDTemplate, CWnd* pParentWnd)
1076: {
1077: m_lpDialogTemplate = MAKEINTRESOURCE(nIDTemplate);
1078: m_hDialogTemplate = NULL;
1079: m_pParentWnd = pParentWnd;
1080: }
1081:
1082: BOOL
1083: CModalDialog::CreateIndirect(HANDLE hDialogTemplate)
1084: {
1085: // must be called on an empty constructed CModalDialog
1086: ASSERT(m_lpDialogTemplate == NULL);
1087: ASSERT(m_hDialogTemplate == NULL);
1088:
1089: m_hDialogTemplate = hDialogTemplate;
1090: return TRUE; // always ok (DoModal actually brings up dialog)
1091: }
1092:
1093: #ifdef _DEBUG
1094: void
1095: CModalDialog::AssertValid() const
1096: {
1097: CDialog::AssertValid();
1098: }
1099:
1100: void
1101: CModalDialog::Dump(CDumpContext& dc) const
1102: {
1103: CDialog::Dump(dc);
1104: dc << "\nm_lpDialogTemplate = " << m_lpDialogTemplate << "\n";
1105: dc << "m_hDialogTemplate = " << m_hDialogTemplate << "\n";
1106: dc << "m_pParentWnd = " << (void *)m_pParentWnd;
1107: }
1108: #endif
1109:
1110: int
1111: CModalDialog::DoModal()
1112: {
1113: HWND hWndParent;
1114: int nResult;
1115:
1116: // can be constructed with a resource template or CreateIndirect
1117: ASSERT(m_lpDialogTemplate != NULL || m_hDialogTemplate != NULL);
1118:
1119: // find parent HWND
1120: if (m_pParentWnd != NULL)
1121: hWndParent = m_pParentWnd->m_hWnd;
1122: else
1123: hWndParent = AfxGetApp()->m_pMainWnd->GetSafeHwnd();
1124:
1125: _AfxHookWindowCreate(this);
1126: if (m_lpDialogTemplate != NULL)
1127: {
1128: nResult = ::DialogBox(AfxGetResourceHandle(), m_lpDialogTemplate,
1129: hWndParent, (DLGPROC)_AfxDlgProc);
1130: }
1131: else
1132: {
1133: #ifdef _NTWIN
1134: nResult = ::DialogBoxIndirect(AfxGetResourceHandle(),
1135: (LPDLGTEMPLATE)m_hDialogTemplate, hWndParent, (DLGPROC)_AfxDlgProc);
1136: #else
1137: nResult = ::DialogBoxIndirect(AfxGetResourceHandle(), m_hDialogTemplate,
1138: hWndParent, (DLGPROC)_AfxDlgProc);
1139: #endif
1140: }
1141:
1142: _AfxUnhookWindowCreate(); // just in case
1143: Detach(); // just in case
1144: return nResult;
1145: }
1146:
1147: /////////////////////////////////////////////////////////////////////////////
1148: // Standard CModalDialog implementation
1149:
1150: void
1151: CModalDialog::OnOK()
1152: {
1153: EndDialog(IDOK);
1154: }
1155:
1156: void
1157: CModalDialog::OnCancel()
1158: {
1159: EndDialog(IDCANCEL);
1160: }
1161:
1162: /////////////////////////////////////////////////////////////////////////////
1163: // CRect for creating windows with the default position/size
1164: const CRect NEAR CFrameWnd::rectDefault(CW_USEDEFAULT, CW_USEDEFAULT,
1165: 0 /* 2*CW_USEDEFAULT */, 0 /* 2*CW_USEDEFAULT */);
1166:
1167: // CWnds for setting z-order with SetWindowPos's pWndInsertAfter parameter
1168: const CWnd NEAR CWnd::wndTop((HWND)0);
1169: const CWnd NEAR CWnd::wndBottom((HWND)1);
1170: const CWnd NEAR CWnd::wndTopMost((HWND)-1);
1171: const CWnd NEAR CWnd::wndNoTopMost((HWND)-2);
1172:
1173: /////////////////////////////////////////////////////////////////////////////
1174: // Message table implementation
1175:
1176: CMessageMap CWnd::messageMap =
1177: {
1178: NULL, // end of chain of message maps
1179: (CMessageEntry FAR*) &CWnd::_messageEntries
1180: };
1181:
1182: CMessageMap* CWnd::GetMessageMap() const
1183: {
1184: return &CWnd::messageMap;
1185: }
1186:
1187:
1188: CMessageEntry BASED_CODE CWnd::_messageEntries[] =
1189: {
1190: ON_WM_COMPAREITEM()
1191: ON_WM_MEASUREITEM()
1192: ON_WM_DRAWITEM()
1193: ON_WM_DELETEITEM()
1194: ON_WM_CTLCOLOR()
1195: ON_WM_DESTROY()
1196: ON_WM_NCDESTROY()
1197: #ifdef _NTWIN
1198: ON_MESSAGE(WM_CTLCOLORMSGBOX, OnNTCtlColor)
1199: ON_MESSAGE(WM_CTLCOLOREDIT, OnNTCtlColor)
1200: ON_MESSAGE(WM_CTLCOLORLISTBOX, OnNTCtlColor)
1201: ON_MESSAGE(WM_CTLCOLORBTN, OnNTCtlColor)
1202: ON_MESSAGE(WM_CTLCOLORDLG, OnNTCtlColor)
1203: ON_MESSAGE(WM_CTLCOLORSCROLLBAR, OnNTCtlColor)
1204: ON_MESSAGE(WM_CTLCOLORSTATIC, OnNTCtlColor)
1205: #endif
1206:
1207: { 0, 0, AfxSig_end, (AFX_PMSG)0 }
1208: };
1209:
1210: union MessageMapFunctions
1211: {
1212: AFX_PMSG pfn; // generic member function pointer
1213:
1214: // specific type safe variants
1215: BOOL (CWnd::*pfn_bD)(CDC *);
1216: BOOL (CWnd::*pfn_bb)(BOOL);
1217: BOOL (CWnd::*pfn_bWww)(CWnd*, UINT, UINT);
1218: HBRUSH (CWnd::*pfn_hDWw)(CDC *, CWnd*, UINT);
1219: int (CWnd::*pfn_iwWw)(UINT, CWnd*, UINT);
1220: int (CWnd::*pfn_iWww)(CWnd*, UINT, UINT);
1221: int (CWnd::*pfn_is)(LPSTR);
1222: LONG (CWnd::*pfn_lwl)(UINT, LONG);
1223: LONG (CWnd::*pfn_lwwM)(UINT, UINT, CMenu *);
1224: void (CWnd::*pfn_vv)(void);
1225:
1226: void (CWnd::*pfn_vw)(UINT);
1227: void (CWnd::*pfn_vww)(UINT, UINT);
1228: void (CWnd::*pfn_vvii)(int, int);
1229: void (CWnd::*pfn_vwww)(UINT, UINT, UINT);
1230: void (CWnd::*pfn_vwii)(UINT, int, int);
1231: void (CWnd::*pfn_vwl)(UINT, LONG);
1232: void (CWnd::*pfn_vbWW)(BOOL, CWnd*, CWnd*);
1233: void (CWnd::*pfn_vD)(CDC *);
1234: void (CWnd::*pfn_vM)(CMenu *);
1235: void (CWnd::*pfn_vMwb)(CMenu *, UINT, BOOL);
1236:
1237: void (CWnd::*pfn_vW)(CWnd*);
1238: void (CWnd::*pfn_vWww)(CWnd*, UINT, UINT);
1239: void (CWnd::*pfn_vWh)(CWnd*, HANDLE);
1240: void (CWnd::*pfn_vwW)(UINT, CWnd*);
1241: void (CWnd::*pfn_vwWb)(UINT, CWnd*, BOOL);
1242: void (CWnd::*pfn_vwwW)(UINT, UINT, CWnd*);
1243: void (CWnd::*pfn_vs)(LPSTR);
1244: UINT (CWnd::*pfn_wp)(CPoint);
1245: UINT (CWnd::*pfn_wv)(void);
1246: BOOL (CWnd::*pfn_bh)(HANDLE);
1247: void (CWnd::*pfn_vPOS)(WINDOWPOS FAR*);
1248: void (CWnd::*pfn_vCALC)(NCCALCSIZE_PARAMS FAR*);
1249: #ifdef _NTWIN
1250: void (CWnd::*pfn_vwp)(UINT, CPoint);
1251: void (CWnd::*pfn_vwwh)(UINT, UINT, HANDLE);
1252: #endif
1253: };
1254:
1255: /////////////////////////////////////////////////////////////////////////////
1256: // Routines for fast search of message maps
1257:
1258:
1259: // Hand tuned routine
1260:
1261: #pragma optimize("qgel", off) // assembler cannot be globally optimized
1262:
1263: #ifdef _NTWIN
1264: // C versions of search routines
1265: static inline CMessageEntry FAR*
1266: FindMessageEntry(CMessageEntry FAR* lpEntry, UINT nMsg, UINT nID)
1267: {
1268: while (lpEntry->nSig != AfxSig_end)
1269: {
1270: if (lpEntry->nMessage == nMsg && lpEntry->nID == nID)
1271: return lpEntry;
1272: lpEntry++;
1273: }
1274: return NULL; // not found
1275: }
1276:
1277: #else
1278: static CMessageEntry FAR* NEAR
1279: FindMessageEntry(CMessageEntry FAR* lpEntry, UINT nMsg, UINT nID)
1280: {
1281: _asm
1282: {
1283: LES BX,lpEntry
1284: MOV AX,nMsg
1285: MOV DX,nID
1286: __loop:
1287: MOV CX,WORD PTR ES:[BX+4] ; nSig (0 => end)
1288: JCXZ __failed
1289: CMP AX,WORD PTR ES:[BX] ; nMessage
1290: JE __found_1
1291: __next:
1292: ADD BX,SIZE CMessageEntry
1293: JMP __loop
1294: __found_1:
1295: CMP DX,WORD PTR ES:[BX+2] ; nID
1296: JNE __next
1297: // found a match
1298: MOV WORD PTR lpEntry,BX
1299: MOV WORD PTR lpEntry+2,ES
1300: JMP __end
1301: __failed:
1302: XOR AX,AX
1303: MOV WORD PTR lpEntry,AX
1304: MOV WORD PTR lpEntry+2,AX
1305: __end:
1306: }
1307: return lpEntry;
1308: }
1309: #endif //_NTWIN
1310:
1311: #pragma optimize("", on) // return to default optimizations
1312:
1313:
1314: /////////////////////////////////////////////////////////////////////////////
1315:
1316: #ifndef iHashMax
1317: // iHashMax must be a power of two
1318: #ifdef _NEARDATA
1319: #define iHashMax 64
1320: #else
1321: #define iHashMax 256
1322: #endif
1323: #endif
1324:
1325: struct MsgCache
1326: {
1327: UINT nMsg;
1328: CMessageEntry FAR* lpEntry;
1329: CMessageMap* pMessageMap;
1330: };
1331:
1332: MsgCache _afxMsgCache[iHashMax];
1333:
1334: LONG
1335: CWnd::WindowProc(UINT nMsg, UINT wParam, LONG lParam)
1336: {
1337: register CMessageMap* pMessageMap;
1338: CMessageEntry FAR* lpEntry;
1339:
1340: if (nMsg == WM_COMMAND) // special case for commands
1341: {
1342: if (OnCommand(wParam, lParam))
1343: return 1L; // command handled
1344: else
1345: return (LONG)DefWindowProc(nMsg, wParam, lParam); // call default handler
1346: }
1347:
1348: pMessageMap = GetMessageMap();
1349: UINT iHash = (_AFX_FP_OFF(pMessageMap) ^ nMsg) & (iHashMax-1);
1350: MsgCache& msgCache = _afxMsgCache[iHash];
1351:
1352: if (nMsg == msgCache.nMsg && pMessageMap == msgCache.pMessageMap)
1353: {
1354: // Cache hit
1355: lpEntry = msgCache.lpEntry;
1356: if (lpEntry == NULL)
1357: return (LONG)DefWindowProc(nMsg, wParam, lParam);
1358: else if (nMsg < 0xC000)
1359: goto LDispatch;
1360: else
1361: goto LDispatchRegistered;
1362: }
1363: else
1364: {
1365: // not in cache, look for it
1366: msgCache.nMsg = nMsg;
1367: msgCache.pMessageMap = pMessageMap;
1368:
1369: for (/* pMessageMap already init'ed */; pMessageMap != NULL;
1370: pMessageMap = pMessageMap->pBaseMessageMap)
1371: {
1372: // This may loop forever if the message maps are not properly
1373: // chained together. Make sure each window class's message map
1374: // points to the base window class's message map.
1375:
1376: if (nMsg < 0xC000)
1377: {
1378: // constant window message
1379: if ((lpEntry = FindMessageEntry(pMessageMap->lpEntries,
1380: nMsg, 0)) != NULL)
1381: {
1382: msgCache.lpEntry = lpEntry;
1383: goto LDispatch;
1384: }
1385: }
1386: else
1387: {
1388: // registered windows message
1389: lpEntry = pMessageMap->lpEntries;
1390:
1391: while ((lpEntry = FindMessageEntry(lpEntry, 0xC000, 0)) != NULL)
1392: {
1393: UINT NEAR* pnID = (UINT NEAR*)(lpEntry->nSig);
1394: ASSERT(*pnID >= 0xC000);
1395: // must be successfully registered
1396: if (*pnID == nMsg)
1397: {
1398: msgCache.lpEntry = lpEntry;
1399: goto LDispatchRegistered;
1400: }
1401: lpEntry++; // keep looking past this one
1402: }
1403: }
1404: }
1405:
1406: msgCache.lpEntry = NULL;
1407: return DefWindowProc(nMsg, wParam, lParam);
1408: }
1409: ASSERT(FALSE); // not reached
1410:
1411:
1412: LDispatch:
1413: ASSERT(nMsg < 0xC000);
1414: union MessageMapFunctions mmf;
1415: mmf.pfn = lpEntry->pfn;
1416:
1417: switch (lpEntry->nSig)
1418: {
1419: default:
1420: ASSERT(FALSE);
1421: return 0;
1422:
1423: case AfxSig_bD:
1424: return (this->*mmf.pfn_bD)(CDC::FromHandle((HDC)wParam));
1425:
1426: case AfxSig_bb:
1427: return (this->*mmf.pfn_bb)((BOOL)wParam);
1428:
1429: case AfxSig_bWww:
1430: return (this->*mmf.pfn_bWww)(CWnd::FromHandle((HWND)wParam),
1.1.1.2 ! root 1431: (short)LOWORD(lParam), HIWORD(lParam));
1.1 root 1432:
1433: #ifdef _NTWIN
1434: case AfxSig_hDWw:
1435: {
1436: ASSERT(nMsg == WM_CTLCOLOR);
1437: struct _AFXCTLCOLOR* pCtl = (struct _AFXCTLCOLOR*)lParam;
1438: return (LONG)((this->*mmf.pfn_hDWw)( CDC::FromHandle(pCtl->hDC),
1439: CWnd::FromHandle(pCtl->hWnd), pCtl->nCtlType));
1440: }
1441: #else
1442: case AfxSig_hDWw:
1443: return (LONG)(UINT)(this->*mmf.pfn_hDWw)(CDC::FromHandle((HDC)wParam),
1444: CWnd::FromHandle((HWND)LOWORD(lParam)), HIWORD(lParam));
1445: #endif
1446:
1447: #ifndef _NTWIN
1448: case AfxSig_iwWw:
1449: return (this->*mmf.pfn_iwWw)(wParam, CWnd::FromHandle((HWND)LOWORD(lParam)),
1450: HIWORD(lParam));
1451: #else
1452: case AfxSig_iwWw:
1453: return (this->*mmf.pfn_iwWw)(LOWORD(wParam),
1454: CWnd::FromHandle((HWND)lParam),
1455: HIWORD(wParam));
1456: #endif
1457:
1458: case AfxSig_iWww:
1459: return (this->*mmf.pfn_iWww)(CWnd::FromHandle((HWND)wParam),
1.1.1.2 ! root 1460: (short)LOWORD(lParam), HIWORD(lParam));
1.1 root 1461:
1462: case AfxSig_is:
1463: return (this->*mmf.pfn_is)((LPSTR)lParam);
1464:
1465: case AfxSig_lwl:
1466: return (this->*mmf.pfn_lwl)(wParam, lParam);
1467:
1468: #ifndef _NTWIN
1469: case AfxSig_lwwM:
1470: return (this->*mmf.pfn_lwwM)(wParam, LOWORD(lParam),
1471: CMenu::FromHandle((HMENU)HIWORD(lParam)));
1472: #else
1473: case AfxSig_lwwM:
1474: return (this->*mmf.pfn_lwwM)((UINT)LOWORD(wParam), (UINT)HIWORD(wParam),
1475: (CMenu*)CMenu::FromHandle((HMENU)lParam));
1476: #endif
1477:
1478: case AfxSig_vv:
1479: (this->*mmf.pfn_vv)();
1480: return 0;
1481:
1482:
1483: case AfxSig_vw: // AfxSig_vb:
1484: (this->*mmf.pfn_vw)(wParam);
1485: return 0;
1486:
1487: case AfxSig_vww:
1488: #ifndef _NTWIN
1489: (this->*mmf.pfn_vww)(wParam, LOWORD(lParam));
1490: #else
1491: (this->*mmf.pfn_vww)(wParam, lParam);
1492: #endif
1493: return 0;
1494:
1495: case AfxSig_vvii:
1496: (this->*mmf.pfn_vvii)(LOWORD(lParam), HIWORD(lParam));
1497: return 0;
1498:
1499: #ifdef _NTWIN
1500: case AfxSig_vwwh:
1501: (this->*mmf.pfn_vwwh)(LOWORD(wParam), HIWORD(wParam), (HANDLE)lParam);
1502: return 0;
1503: #endif
1504:
1505: case AfxSig_vwww:
1506: (this->*mmf.pfn_vwww)(wParam, LOWORD(lParam), HIWORD(lParam));
1507: return 0;
1508:
1509: case AfxSig_vwii:
1510: (this->*mmf.pfn_vwii)(wParam, LOWORD(lParam), HIWORD(lParam));
1511: return 0;
1512:
1513: case AfxSig_vwl:
1514: (this->*mmf.pfn_vwl)(wParam, lParam);
1515: return 0;
1516:
1517: #ifndef _NTWIN
1518: case AfxSig_vbWW:
1519: (this->*mmf.pfn_vbWW)((BOOL)wParam,
1520: CWnd::FromHandle((HWND)LOWORD(lParam)),
1521: CWnd::FromHandle((HWND)HIWORD(lParam)));
1522: return 0;
1523: #else
1524: case AfxSig_vbWW:
1525: (this->*mmf.pfn_vbWW)(m_hWnd == (HWND)lParam,
1526: CWnd::FromHandle((HWND)lParam),
1527: CWnd::FromHandle((HWND)wParam));
1528: return 0;
1529: #endif
1530:
1531: case AfxSig_vD:
1532: (this->*mmf.pfn_vD)(CDC::FromHandle((HDC)wParam));
1533: return 0;
1534:
1535: case AfxSig_vM:
1536: (this->*mmf.pfn_vM)(CMenu::FromHandle((HMENU)wParam));
1537: return 0;
1538:
1539: case AfxSig_vMwb:
1540: (this->*mmf.pfn_vMwb)(CMenu::FromHandle((HMENU)wParam),
1541: LOWORD(lParam), (BOOL)HIWORD(lParam));
1542: return 0;
1543:
1544:
1545: case AfxSig_vW:
1546: (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)wParam));
1547: return 0;
1548:
1549: case AfxSig_vWww:
1550: (this->*mmf.pfn_vWww)(CWnd::FromHandle((HWND)wParam), LOWORD(lParam),
1551: HIWORD(lParam));
1552: return 0;
1553:
1554: #ifndef _NTWIN
1555: case AfxSig_vWh:
1556: (this->*mmf.pfn_vWh)(CWnd::FromHandle((HWND)wParam),
1557: (HANDLE)LOWORD(lParam));
1558: return 0;
1559: #else
1560: case AfxSig_vWh:
1561: (this->*mmf.pfn_vWh)(CWnd::FromHandle((HWND)wParam),
1562: (HANDLE)lParam);
1563: return 0;
1564: #endif
1565:
1566: #ifndef _NTWIN
1567: case AfxSig_vwW:
1568: (this->*mmf.pfn_vwW)(wParam, CWnd::FromHandle((HWND)LOWORD(lParam)));
1569: return 0;
1570: #else
1571: case AfxSig_vwW:
1572: (this->*mmf.pfn_vwW)(wParam, CWnd::FromHandle((HWND)lParam));
1573: return 0;
1574: #endif
1575:
1576: #ifndef _NTWIN
1577: case AfxSig_vwWb:
1578: (this->*mmf.pfn_vwWb)(wParam, CWnd::FromHandle((HWND)LOWORD(lParam)),
1579: (BOOL)HIWORD(lParam));
1580: return 0;
1581: #else
1582: case AfxSig_vwWb:
1583: (this->*mmf.pfn_vwWb)((UINT)(LOWORD(wParam)),
1584: CWnd::FromHandle((HWND)lParam),
1585: (BOOL)(!(!(HIWORD(wParam)))));
1586: return 0;
1587: #endif //_NTWIN
1588:
1589: #ifndef _NTWIN
1590: case AfxSig_vwwW:
1591: (this->*mmf.pfn_vwwW)(wParam, LOWORD(lParam),
1592: CWnd::FromHandle((HWND)HIWORD(lParam)));
1593: return 0;
1594: #else
1595: case AfxSig_vwwW:
1.1.1.2 ! root 1596: (this->*mmf.pfn_vwwW)((short)LOWORD(wParam), (short)HIWORD(wParam),
1.1 root 1597: CWnd::FromHandle((HWND)lParam));
1598: return 0;
1599: #endif
1600:
1601: case AfxSig_vs:
1602: (this->*mmf.pfn_vs)((LPSTR)lParam);
1603: return 0;
1604:
1605: #ifndef _NTWIN
1606: case AfxSig_wp:
1607: return (this->*mmf.pfn_wp)(*(CPoint*)&lParam);
1608: #else
1609: case AfxSig_wp:
1610: {
1611: CPoint point((DWORD)lParam);
1612: return (this->*mmf.pfn_wp)(point);
1613: }
1614:
1615: case AfxSig_vwp:
1616: {
1617: CPoint point((DWORD)lParam);
1618: (this->*mmf.pfn_vwp)(wParam, point);
1619: return 0;
1620: }
1621: #endif
1622:
1623: case AfxSig_wv: // AfxSig_bv, AfxSig_wv
1624: return (this->*mmf.pfn_wv)();
1625:
1626: case AfxSig_bh:
1627: return (this->*mmf.pfn_bh)((HANDLE)wParam);
1628:
1629: case AfxSig_vCALC:
1630: (this->*mmf.pfn_vCALC)((NCCALCSIZE_PARAMS FAR*)lParam);
1631: return 0;
1632:
1633: case AfxSig_vPOS:
1634: (this->*mmf.pfn_vPOS)((WINDOWPOS FAR*)lParam);
1635: return 0;
1636: }
1637: ASSERT(FALSE); // not reached
1638:
1639: LDispatchRegistered: // for registered windows messages
1640: ASSERT(nMsg >= 0xC000);
1641: mmf.pfn = lpEntry->pfn;
1642: return (this->*mmf.pfn_lwl)(wParam, lParam);
1643: }
1644:
1645: BOOL CWnd::OnCommand(UINT wParam, LONG lParam)
1646: {
1647: #ifdef _NTWIN
1648: UINT nID = LOWORD(wParam);
1649: HWND hWndCtrl = (HWND)lParam;
1650: UINT nNotifyCode = HIWORD(wParam); // control specific
1651: #else
1652: UINT nID = wParam;
1653: HWND hWndCtrl = (HWND)LOWORD(lParam);
1654: UINT nNotifyCode = HIWORD(lParam); // control specific
1655: #endif
1656: if (nID == 0)
1657: return FALSE; // 0 control IDs are not allowed !
1658:
1659: // default routing for command messages (through closure table)
1660: if (hWndCtrl == NULL)
1661: nNotifyCode = 0; // accelerators are not special
1662:
1663: // check in message map table for matching control ID
1664: register CMessageMap* pMessageMap;
1665: register CMessageEntry FAR* lpEntry;
1666:
1667: for (pMessageMap = GetMessageMap(); pMessageMap != NULL;
1668: pMessageMap = pMessageMap->pBaseMessageMap)
1669: {
1670: if ((lpEntry = FindMessageEntry(pMessageMap->lpEntries,
1671: nNotifyCode, nID)) != NULL)
1672: {
1673: #ifdef _DEBUG
1674: // diagnostic trace reporting of command notifications
1675: if (afxTraceFlags & 8) // if command reporting
1676: {
1677: if (nNotifyCode == 0)
1678: {
1679: TRACE("SENDING command %d to %s window\n", nID,
1680: GetRuntimeClass()->m_pszClassName);
1681: }
1682: else if (afxTraceFlags & 4) // if verbose windows messages
1683: {
1684: TRACE("SENDING control notification %d from control id %d "
1685: "to %s window\n", nNotifyCode, nID,
1686: GetRuntimeClass()->m_pszClassName);
1687: }
1688: }
1689: #endif
1690: // dispatch it
1691: (this->*lpEntry->pfn)();
1692: return TRUE; // handled
1693: }
1694: }
1695:
1696: #ifdef _DEBUG
1697: if (afxTraceFlags & 8)
1698: {
1699: if (nNotifyCode == 0)
1700: {
1701: TRACE("IGNORING command %d sent to %s window\n", nID,
1702: GetRuntimeClass()->m_pszClassName);
1703: }
1704: else if (afxTraceFlags & 4) // if verbose windows messages
1705: {
1706: TRACE("IGNORING control notification %d from control id %d "
1707: "to %s window\n", nNotifyCode, nID,
1708: GetRuntimeClass()->m_pszClassName);
1709: }
1710: }
1711: #endif
1712:
1713: return FALSE; // not handled
1714: }
1715:
1716:
1717:
1718: /////////////////////////////////////////////////////////////////////////////
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.