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