home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / wincore.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  109KB  |  3,948 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 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 related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #ifndef _AFX_NO_OCC_SUPPORT
  13. #include "occimpl.h"
  14. #endif
  15.  
  16. #pragma warning(disable:4706)
  17. #define COMPILE_MULTIMON_STUBS
  18. #include <multimon.h>
  19. #pragma warning(default:4706)
  20.  
  21. #ifdef AFX_CORE1_SEG
  22. #pragma code_seg(AFX_CORE1_SEG)
  23. #endif
  24.  
  25. #ifdef _DEBUG
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29.  
  30. #define new DEBUG_NEW
  31.  
  32. /////////////////////////////////////////////////////////////////////////////
  33. // Globals
  34.  
  35. const UINT CWnd::m_nMsgDragList = ::RegisterWindowMessage(DRAGLISTMSGSTRING);
  36.  
  37. // CWnds for setting z-order with SetWindowPos's pWndInsertAfter parameter
  38. const AFX_DATADEF CWnd CWnd::wndTop(HWND_TOP);
  39. const AFX_DATADEF CWnd CWnd::wndBottom(HWND_BOTTOM);
  40. const AFX_DATADEF CWnd CWnd::wndTopMost(HWND_TOPMOST);
  41. const AFX_DATADEF CWnd CWnd::wndNoTopMost(HWND_NOTOPMOST);
  42.  
  43. const TCHAR _afxWnd[] = AFX_WND;
  44. const TCHAR _afxWndControlBar[] = AFX_WNDCONTROLBAR;
  45. const TCHAR _afxWndMDIFrame[] = AFX_WNDMDIFRAME;
  46. const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;
  47. const TCHAR _afxWndOleControl[] = AFX_WNDOLECONTROL;
  48.  
  49. /////////////////////////////////////////////////////////////////////////////
  50. // CWnd construction
  51.  
  52. CWnd::CWnd()
  53. {
  54.     AFX_ZERO_INIT_OBJECT(CCmdTarget);
  55. }
  56.  
  57. CWnd::CWnd(HWND hWnd)
  58. {
  59.     AFX_ZERO_INIT_OBJECT(CCmdTarget);
  60.     m_hWnd = hWnd;
  61. }
  62.  
  63. // Change a window's style
  64.  
  65. AFX_STATIC BOOL AFXAPI _AfxModifyStyle(HWND hWnd, int nStyleOffset,
  66.     DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  67. {
  68.     ASSERT(hWnd != NULL);
  69.     DWORD dwStyle = ::GetWindowLong(hWnd, nStyleOffset);
  70.     DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  71.     if (dwStyle == dwNewStyle)
  72.         return FALSE;
  73.  
  74.     ::SetWindowLong(hWnd, nStyleOffset, dwNewStyle);
  75.     if (nFlags != 0)
  76.     {
  77.         ::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
  78.             SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  79.     }
  80.     return TRUE;
  81. }
  82.  
  83. BOOL PASCAL
  84. CWnd::ModifyStyle(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  85. {
  86.     return _AfxModifyStyle(hWnd, GWL_STYLE, dwRemove, dwAdd, nFlags);
  87. }
  88.  
  89. BOOL PASCAL
  90. CWnd::ModifyStyleEx(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  91. {
  92.     return _AfxModifyStyle(hWnd, GWL_EXSTYLE, dwRemove, dwAdd, nFlags);
  93. }
  94.  
  95. /////////////////////////////////////////////////////////////////////////////
  96. // Special helpers for certain windows messages
  97.  
  98. AFX_STATIC void AFXAPI _AfxPreInitDialog(
  99.     CWnd* pWnd, LPRECT lpRectOld, DWORD* pdwStyleOld)
  100. {
  101.     ASSERT(lpRectOld != NULL);
  102.     ASSERT(pdwStyleOld != NULL);
  103.  
  104.     pWnd->GetWindowRect(lpRectOld);
  105.     *pdwStyleOld = pWnd->GetStyle();
  106. }
  107.  
  108. AFX_STATIC void AFXAPI _AfxPostInitDialog(
  109.     CWnd* pWnd, const RECT& rectOld, DWORD dwStyleOld)
  110. {
  111.     // must be hidden to start with
  112.     if (dwStyleOld & WS_VISIBLE)
  113.         return;
  114.  
  115.     // must not be visible after WM_INITDIALOG
  116.     if (pWnd->GetStyle() & (WS_VISIBLE|WS_CHILD))
  117.         return;
  118.  
  119.     // must not move during WM_INITDIALOG
  120.     CRect rect;
  121.     pWnd->GetWindowRect(rect);
  122.     if (rectOld.left != rect.left || rectOld.top != rect.top)
  123.         return;
  124.  
  125.     // must be unowned or owner disabled
  126.     CWnd* pParent = pWnd->GetWindow(GW_OWNER);
  127.     if (pParent != NULL && pParent->IsWindowEnabled())
  128.         return;
  129.  
  130.     if (!pWnd->CheckAutoCenter())
  131.         return;
  132.  
  133.     // center modal dialog boxes/message boxes
  134.     pWnd->CenterWindow();
  135. }
  136.  
  137. AFX_STATIC void AFXAPI
  138. _AfxHandleActivate(CWnd* pWnd, WPARAM nState, CWnd* pWndOther)
  139. {
  140.     ASSERT(pWnd != NULL);
  141.  
  142.     // send WM_ACTIVATETOPLEVEL when top-level parents change
  143.     CWnd* pTopLevel;
  144.     if (!(pWnd->GetStyle() & WS_CHILD) &&
  145.         (pTopLevel = pWnd->GetTopLevelParent()) != pWndOther->GetTopLevelParent())
  146.     {
  147.         // lParam points to window getting the WM_ACTIVATE message and
  148.         //  hWndOther from the WM_ACTIVATE.
  149.         HWND hWnd2[2];
  150.         hWnd2[0] = pWnd->m_hWnd;
  151.         hWnd2[1] = pWndOther->GetSafeHwnd();
  152.         // send it...
  153.         pTopLevel->SendMessage(WM_ACTIVATETOPLEVEL, nState, (LPARAM)&hWnd2[0]);
  154.     }
  155. }
  156.  
  157. AFX_STATIC BOOL AFXAPI
  158. _AfxHandleSetCursor(CWnd* pWnd, UINT nHitTest, UINT nMsg)
  159. {
  160.     if (nHitTest == HTERROR &&
  161.         (nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN ||
  162.          nMsg == WM_RBUTTONDOWN))
  163.     {
  164.         // activate the last active window if not active
  165.         CWnd* pLastActive = pWnd->GetTopLevelParent();
  166.         if (pLastActive != NULL)
  167.             pLastActive = pLastActive->GetLastActivePopup();
  168.         if (pLastActive != NULL &&
  169.             pLastActive != CWnd::GetForegroundWindow() &&
  170.             pLastActive->IsWindowEnabled())
  171.         {
  172.             pLastActive->SetForegroundWindow();
  173.             return TRUE;
  174.         }
  175.     }
  176.     return FALSE;
  177. }
  178.  
  179. /////////////////////////////////////////////////////////////////////////////
  180. // Official way to send message to a CWnd
  181.  
  182. LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,
  183.     WPARAM wParam = 0, LPARAM lParam = 0)
  184. {
  185.     _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  186.     MSG oldState = pThreadState->m_lastSentMsg;   // save for nesting
  187.     pThreadState->m_lastSentMsg.hwnd = hWnd;
  188.     pThreadState->m_lastSentMsg.message = nMsg;
  189.     pThreadState->m_lastSentMsg.wParam = wParam;
  190.     pThreadState->m_lastSentMsg.lParam = lParam;
  191.  
  192. #ifdef _DEBUG
  193.     if (afxTraceFlags & traceWinMsg)
  194.         _AfxTraceMsg(_T("WndProc"), &pThreadState->m_lastSentMsg);
  195. #endif
  196.  
  197.     // Catch exceptions thrown outside the scope of a callback
  198.     // in debug builds and warn the user.
  199.     LRESULT lResult;
  200.     TRY
  201.     {
  202. #ifndef _AFX_NO_OCC_SUPPORT
  203.         // special case for WM_DESTROY
  204.         if ((nMsg == WM_DESTROY) && (pWnd->m_pCtrlCont != NULL))
  205.             pWnd->m_pCtrlCont->OnUIActivate(NULL);
  206. #endif
  207.  
  208.         // special case for WM_INITDIALOG
  209.         CRect rectOld;
  210.         DWORD dwStyle = 0;
  211.         if (nMsg == WM_INITDIALOG)
  212.             _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
  213.  
  214.         // delegate to object's WindowProc
  215.         lResult = pWnd->WindowProc(nMsg, wParam, lParam);
  216.  
  217.         // more special case for WM_INITDIALOG
  218.         if (nMsg == WM_INITDIALOG)
  219.             _AfxPostInitDialog(pWnd, rectOld, dwStyle);
  220.     }
  221.     CATCH_ALL(e)
  222.     {
  223.         lResult = AfxGetThread()->ProcessWndProcException(e, &pThreadState->m_lastSentMsg);
  224.         TRACE1("Warning: Uncaught exception in WindowProc (returning %ld).\n",
  225.             lResult);
  226.         DELETE_EXCEPTION(e);
  227.     }
  228.     END_CATCH_ALL
  229.  
  230.     pThreadState->m_lastSentMsg = oldState;
  231.     return lResult;
  232. }
  233.  
  234. const MSG* PASCAL CWnd::GetCurrentMessage()
  235. {
  236.     // fill in time and position when asked for
  237.     _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  238.     pThreadState->m_lastSentMsg.time = ::GetMessageTime();
  239.     pThreadState->m_lastSentMsg.pt = CPoint(::GetMessagePos());
  240.     return &pThreadState->m_lastSentMsg;
  241. }
  242.  
  243. LRESULT CWnd::Default()
  244. {
  245.     // call DefWindowProc with the last message
  246.     _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  247.     return DefWindowProc(pThreadState->m_lastSentMsg.message,
  248.         pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam);
  249. }
  250.  
  251. /////////////////////////////////////////////////////////////////////////////
  252. // Map from HWND to CWnd*
  253.  
  254. #include "fixalloc.h"
  255.  
  256. class CTempWnd : public CWnd
  257. {
  258.     DECLARE_DYNCREATE(CTempWnd)
  259.     DECLARE_FIXED_ALLOC(CTempWnd);
  260. };
  261.  
  262. CHandleMap* PASCAL afxMapHWND(BOOL bCreate)
  263. {
  264.     AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  265.     if (pState->m_pmapHWND == NULL && bCreate)
  266.     {
  267.         BOOL bEnable = AfxEnableMemoryTracking(FALSE);
  268. #ifndef _AFX_PORTABLE
  269.         _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
  270. #endif
  271.         pState->m_pmapHWND = new CHandleMap(RUNTIME_CLASS(CTempWnd),
  272.             offsetof(CWnd, m_hWnd));
  273.  
  274. #ifndef _AFX_PORTABLE
  275.         AfxSetNewHandler(pnhOldHandler);
  276. #endif
  277.         AfxEnableMemoryTracking(bEnable);
  278.     }
  279.     return pState->m_pmapHWND;
  280. }
  281.  
  282. CWnd* PASCAL CWnd::FromHandle(HWND hWnd)
  283. {
  284.     CHandleMap* pMap = afxMapHWND(TRUE); //create map if not exist
  285.     ASSERT(pMap != NULL);
  286.     CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd);
  287.  
  288. #ifndef _AFX_NO_OCC_SUPPORT
  289.     pWnd->AttachControlSite(pMap);
  290. #endif
  291.  
  292.     ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
  293.     return pWnd;
  294. }
  295.  
  296. CWnd* PASCAL CWnd::FromHandlePermanent(HWND hWnd)
  297. {
  298.     CHandleMap* pMap = afxMapHWND();
  299.     CWnd* pWnd = NULL;
  300.     if (pMap != NULL)
  301.     {
  302.         // only look in the permanent map - does no allocations
  303.         pWnd = (CWnd*)pMap->LookupPermanent(hWnd);
  304.         ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
  305.     }
  306.     return pWnd;
  307. }
  308.  
  309. BOOL CWnd::Attach(HWND hWndNew)
  310. {
  311.     ASSERT(m_hWnd == NULL);     // only attach once, detach on destroy
  312.     ASSERT(FromHandlePermanent(hWndNew) == NULL);
  313.         // must not already be in permanent map
  314.  
  315.     if (hWndNew == NULL)
  316.         return FALSE;
  317.  
  318.     CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist
  319.     ASSERT(pMap != NULL);
  320.  
  321.     pMap->SetPermanent(m_hWnd = hWndNew, this);
  322.  
  323. #ifndef _AFX_NO_OCC_SUPPORT
  324.     AttachControlSite(pMap);
  325. #endif
  326.  
  327.     return TRUE;
  328. }
  329.  
  330. HWND CWnd::Detach()
  331. {
  332.     HWND hWnd = m_hWnd;
  333.     if (hWnd != NULL)
  334.     {
  335.         CHandleMap* pMap = afxMapHWND(); // don't create if not exist
  336.         if (pMap != NULL)
  337.             pMap->RemoveHandle(m_hWnd);
  338.     m_hWnd = NULL;
  339.     }
  340.  
  341. #ifndef _AFX_NO_OCC_SUPPORT
  342.     m_pCtrlSite = NULL;
  343. #endif
  344.  
  345.     return hWnd;
  346. }
  347.  
  348. void CWnd::PreSubclassWindow()
  349. {
  350.     // no default processing
  351. }
  352.  
  353. /////////////////////////////////////////////////////////////////////////////
  354. // The WndProc for all CWnd's and derived classes
  355.  
  356. LRESULT CALLBACK
  357. AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  358. {
  359.     // special message which identifies the window as using AfxWndProc
  360.     if (nMsg == WM_QUERYAFXWNDPROC)
  361.         return 1;
  362.  
  363.     // all other messages route through message map
  364.     CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  365.     ASSERT(pWnd != NULL);
  366.     ASSERT(pWnd->m_hWnd == hWnd);
  367.     return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
  368. }
  369.  
  370. // always indirectly accessed via AfxGetAfxWndProc
  371. WNDPROC AFXAPI AfxGetAfxWndProc()
  372. {
  373. #ifdef _AFXDLL
  374.     return AfxGetModuleState()->m_pfnAfxWndProc;
  375. #else
  376.     return &AfxWndProc;
  377. #endif
  378. }
  379.  
  380. /////////////////////////////////////////////////////////////////////////////
  381. // Special WndProcs (activation handling & gray dialogs)
  382.  
  383. AFX_STATIC_DATA const TCHAR _afxOldWndProc[] = _T("AfxOldWndProc423");
  384.  
  385. LRESULT CALLBACK
  386. _AfxActivationWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  387. {
  388.     WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _afxOldWndProc);
  389.     ASSERT(oldWndProc != NULL);
  390.  
  391.     LRESULT lResult = 0;
  392.     TRY
  393.     {
  394.         BOOL bCallDefault = TRUE;
  395.         switch (nMsg)
  396.         {
  397.         case WM_INITDIALOG:
  398.             {
  399.                 DWORD dwStyle;
  400.                 CRect rectOld;
  401.                 CWnd* pWnd = CWnd::FromHandle(hWnd);
  402.                 _AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
  403.                 bCallDefault = FALSE;
  404.                 lResult = CallWindowProc(oldWndProc, hWnd, nMsg, wParam, lParam);
  405.                 _AfxPostInitDialog(pWnd, rectOld, dwStyle);
  406.             }
  407.             break;
  408.  
  409.         case WM_ACTIVATE:
  410.             _AfxHandleActivate(CWnd::FromHandle(hWnd), wParam,
  411.                 CWnd::FromHandle((HWND)lParam));
  412.             break;
  413.  
  414.         case WM_SETCURSOR:
  415.             bCallDefault = !_AfxHandleSetCursor(CWnd::FromHandle(hWnd),
  416.                 (short)LOWORD(lParam), HIWORD(lParam));
  417.             break;
  418.  
  419.         case WM_NCDESTROY:
  420.             SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);
  421.             RemoveProp(hWnd, _afxOldWndProc);
  422.             GlobalDeleteAtom(GlobalFindAtom(_afxOldWndProc));
  423.             break;
  424.         }
  425.  
  426.         // call original wndproc for default handling
  427.         if (bCallDefault)
  428.             lResult = CallWindowProc(oldWndProc, hWnd, nMsg, wParam, lParam);
  429.     }
  430.     CATCH_ALL(e)
  431.     {
  432.         // handle exception
  433.         MSG msg;
  434.         msg.hwnd = hWnd;
  435.         msg.message = nMsg;
  436.         msg.wParam = wParam;
  437.         msg.lParam = lParam;
  438.         lResult = AfxGetThread()->ProcessWndProcException(e, &msg);
  439.         TRACE1("Warning: Uncaught exception in _AfxActivationWndProc (returning %ld).\n",
  440.             lResult);
  441.         DELETE_EXCEPTION(e);
  442.     }
  443.     END_CATCH_ALL
  444.  
  445.     return lResult;
  446. }
  447.  
  448. #ifndef _AFX_NO_GRAYDLG_SUPPORT
  449. LRESULT CALLBACK
  450. _AfxGrayBackgroundWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
  451. {
  452.     // handle standard gray backgrounds if enabled
  453.     _AFX_WIN_STATE* pWinState = _afxWinState;
  454.     if (pWinState->m_hDlgBkBrush != NULL &&
  455.         (nMsg == WM_CTLCOLORBTN || nMsg == WM_CTLCOLORDLG ||
  456.          nMsg == WM_CTLCOLORSTATIC || nMsg == WM_CTLCOLORSCROLLBAR ||
  457.          nMsg == WM_CTLCOLORLISTBOX) &&
  458.         CWnd::GrayCtlColor((HDC)wParam, (HWND)lParam,
  459.             (UINT)(nMsg - WM_CTLCOLORMSGBOX),
  460.             pWinState->m_hDlgBkBrush, pWinState->m_crDlgTextClr))
  461.     {
  462.         return (LRESULT)pWinState->m_hDlgBkBrush;
  463.     }
  464.  
  465.     // do standard activation related things as well
  466.     return _AfxActivationWndProc(hWnd, nMsg, wParam, lParam);
  467. }
  468. #else  //!_AFX_NO_GRAYDLG_SUPPORT
  469. #define _AfxGrayBackgroundWndProc _AfxActivationWndProc
  470. #endif //_AFX_NO_GRAYDLG_SUPPORT
  471.  
  472. /////////////////////////////////////////////////////////////////////////////
  473. // Window creation hooks
  474.  
  475. LRESULT CALLBACK
  476. _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
  477. {
  478.     _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  479.     if (code != HCBT_CREATEWND)
  480.     {
  481.         // wait for HCBT_CREATEWND just pass others on...
  482.         return CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
  483.             wParam, lParam);
  484.     }
  485.  
  486.     ASSERT(lParam != NULL);
  487.     LPCREATESTRUCT lpcs = ((LPCBT_CREATEWND)lParam)->lpcs;
  488.     ASSERT(lpcs != NULL);
  489.  
  490.     CWnd* pWndInit = pThreadState->m_pWndInit;
  491.     BOOL bContextIsDLL = afxContextIsDLL;
  492.     if (pWndInit != NULL || (!(lpcs->style & WS_CHILD) && !bContextIsDLL))
  493.     {
  494.         // Note: special check to avoid subclassing the IME window
  495.         if (_afxDBCS)
  496.         {
  497.             // check for cheap CS_IME style first...
  498.             if (GetClassLong((HWND)wParam, GCL_STYLE) & CS_IME)
  499.                 goto lCallNextHook;
  500.  
  501.             // get class name of the window that is being created
  502.             LPCTSTR pszClassName;
  503.             TCHAR szClassName[_countof("ime")+1];
  504.             if (HIWORD(lpcs->lpszClass))
  505.             {
  506.                 pszClassName = lpcs->lpszClass;
  507.             }
  508.             else
  509.             {
  510.                 szClassName[0] = '\0';
  511.                 GlobalGetAtomName((ATOM)lpcs->lpszClass, szClassName, _countof(szClassName));
  512.                 pszClassName = szClassName;
  513.             }
  514.  
  515.             // a little more expensive to test this way, but necessary...
  516.             if (lstrcmpi(pszClassName, _T("ime")) == 0)
  517.                 goto lCallNextHook;
  518.         }
  519.  
  520.         ASSERT(wParam != NULL); // should be non-NULL HWND
  521.         HWND hWnd = (HWND)wParam;
  522.         WNDPROC oldWndProc;
  523.         if (pWndInit != NULL)
  524.         {
  525. #ifdef _AFXDLL
  526.             AFX_MANAGE_STATE(pWndInit->m_pModuleState);
  527. #endif
  528.  
  529.             // the window should not be in the permanent map at this time
  530.             ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);
  531.  
  532.             // connect the HWND to pWndInit...
  533.             pWndInit->Attach(hWnd);
  534.             // allow other subclassing to occur first
  535.             pWndInit->PreSubclassWindow();
  536.  
  537.             WNDPROC *pOldWndProc = pWndInit->GetSuperWndProcAddr();
  538.             ASSERT(pOldWndProc != NULL);
  539.  
  540. #ifndef _AFX_NO_CTL3D_SUPPORT
  541.             _AFX_CTL3D_STATE* pCtl3dState;
  542.             DWORD dwFlags;
  543.             if (!afxData.bWin4 && !bContextIsDLL &&
  544.                 (pCtl3dState = _afxCtl3dState.GetDataNA()) != NULL &&
  545.                 pCtl3dState->m_pfnSubclassDlgEx != NULL &&
  546.                 (dwFlags = AfxCallWndProc(pWndInit, hWnd, WM_QUERY3DCONTROLS)) != 0)
  547.             {
  548.                 // was the class registered with AfxWndProc?
  549.                 WNDPROC afxWndProc = AfxGetAfxWndProc();
  550.                 BOOL bAfxWndProc = ((WNDPROC)
  551.                     GetWindowLong(hWnd, GWL_WNDPROC) == afxWndProc);
  552.  
  553.                 pCtl3dState->m_pfnSubclassDlgEx(hWnd, dwFlags);
  554.  
  555.                 // subclass the window if not already wired to AfxWndProc
  556.                 if (!bAfxWndProc)
  557.                 {
  558.                     // subclass the window with standard AfxWndProc
  559.                     oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
  560.                         (DWORD)afxWndProc);
  561.                     ASSERT(oldWndProc != NULL);
  562.                     *pOldWndProc = oldWndProc;
  563.                 }
  564.             }
  565.             else
  566. #endif
  567.             {
  568.                 // subclass the window with standard AfxWndProc
  569.                 WNDPROC afxWndProc = AfxGetAfxWndProc();
  570.                 oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
  571.                     (DWORD)afxWndProc);
  572.                 ASSERT(oldWndProc != NULL);
  573.                 if (oldWndProc != afxWndProc)
  574.                     *pOldWndProc = oldWndProc;
  575.             }
  576.             pThreadState->m_pWndInit = NULL;
  577.         }
  578.         else
  579.         {
  580.             ASSERT(!bContextIsDLL);   // should never get here
  581.  
  582.             // subclass the window with the proc which does gray backgrounds
  583.             oldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
  584.             if (oldWndProc != NULL && GetProp(hWnd, _afxOldWndProc) == NULL)
  585.             {
  586.                 SetProp(hWnd, _afxOldWndProc, oldWndProc);
  587.                 if ((WNDPROC)GetProp(hWnd, _afxOldWndProc) == oldWndProc)
  588.                 {
  589.                     GlobalAddAtom(_afxOldWndProc);
  590.                     SetWindowLong(hWnd, GWL_WNDPROC,
  591.                         (DWORD)(pThreadState->m_bDlgCreate ?
  592.                             _AfxGrayBackgroundWndProc : _AfxActivationWndProc));
  593.                     ASSERT(oldWndProc != NULL);
  594.                 }
  595.             }
  596.         }
  597.     }
  598.  
  599. lCallNextHook:
  600.     LRESULT lResult = CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
  601.         wParam, lParam);
  602.  
  603. #ifndef _AFXDLL
  604.     if (bContextIsDLL)
  605.     {
  606.         ::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
  607.         pThreadState->m_hHookOldCbtFilter = NULL;
  608.     }
  609. #endif
  610.     return lResult;
  611. }
  612.  
  613. void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
  614. {
  615.     _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  616.     if (pThreadState->m_pWndInit == pWnd)
  617.         return;
  618.  
  619.     if (pThreadState->m_hHookOldCbtFilter == NULL)
  620.     {
  621.         pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,
  622.             _AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
  623.         if (pThreadState->m_hHookOldCbtFilter == NULL)
  624.             AfxThrowMemoryException();
  625.     }
  626.     ASSERT(pThreadState->m_hHookOldCbtFilter != NULL);
  627.     ASSERT(pWnd != NULL);
  628.     ASSERT(pWnd->m_hWnd == NULL);   // only do once
  629.  
  630.     ASSERT(pThreadState->m_pWndInit == NULL);   // hook not already in progress
  631.     pThreadState->m_pWndInit = pWnd;
  632. }
  633.  
  634. BOOL AFXAPI AfxUnhookWindowCreate()
  635. {
  636.     _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  637. #ifndef _AFXDLL
  638.     if (afxContextIsDLL && pThreadState->m_hHookOldCbtFilter != NULL)
  639.     {
  640.         ::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
  641.         pThreadState->m_hHookOldCbtFilter = NULL;
  642.     }
  643. #endif
  644.     if (pThreadState->m_pWndInit != NULL)
  645.     {
  646.         pThreadState->m_pWndInit = NULL;
  647.         return FALSE;   // was not successfully hooked
  648.     }
  649.     return TRUE;
  650. }
  651.  
  652. /////////////////////////////////////////////////////////////////////////////
  653. // CWnd creation
  654.  
  655. BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
  656.         LPCTSTR lpszWindowName, DWORD dwStyle,
  657.         const RECT& rect, CWnd* pParentWnd, UINT nID,
  658.         LPVOID lpParam /* = NULL */)
  659. {
  660.     return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
  661.         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  662.         pParentWnd->GetSafeHwnd(), (HMENU)nID, lpParam);
  663. }
  664.  
  665. BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
  666.     LPCTSTR lpszWindowName, DWORD dwStyle,
  667.     int x, int y, int nWidth, int nHeight,
  668.     HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
  669. {
  670.     // allow modification of several common create parameters
  671.     CREATESTRUCT cs;
  672.     cs.dwExStyle = dwExStyle;
  673.     cs.lpszClass = lpszClassName;
  674.     cs.lpszName = lpszWindowName;
  675.     cs.style = dwStyle;
  676.     cs.x = x;
  677.     cs.y = y;
  678.     cs.cx = nWidth;
  679.     cs.cy = nHeight;
  680.     cs.hwndParent = hWndParent;
  681.     cs.hMenu = nIDorHMenu;
  682.     cs.hInstance = AfxGetInstanceHandle();
  683.     cs.lpCreateParams = lpParam;
  684.  
  685.     if (!PreCreateWindow(cs))
  686.     {
  687.         PostNcDestroy();
  688.         return FALSE;
  689.     }
  690.  
  691.     AfxHookWindowCreate(this);
  692.     HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
  693.             cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
  694.             cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
  695.  
  696. #ifdef _DEBUG
  697.     if (hWnd == NULL)
  698.     {
  699.         TRACE1("Warning: Window creation failed: GetLastError returns 0x%8.8X\n",
  700.             GetLastError());
  701.     }
  702. #endif
  703.  
  704.     if (!AfxUnhookWindowCreate())
  705.         PostNcDestroy();        // cleanup if CreateWindowEx fails too soon
  706.  
  707.     if (hWnd == NULL)
  708.         return FALSE;
  709.     ASSERT(hWnd == m_hWnd); // should have been set in send msg hook
  710.     return TRUE;
  711. }
  712.  
  713. // for child windows
  714. BOOL CWnd::PreCreateWindow(CREATESTRUCT& cs)
  715. {
  716.     if (cs.lpszClass == NULL)
  717.     {
  718.         // make sure the default window class is registered
  719.         VERIFY(AfxDeferRegisterClass(AFX_WND_REG));
  720.  
  721.         // no WNDCLASS provided - use child window default
  722.         ASSERT(cs.style & WS_CHILD);
  723.         cs.lpszClass = _afxWnd;
  724.     }
  725.     return TRUE;
  726. }
  727.  
  728. BOOL CWnd::Create(LPCTSTR lpszClassName,
  729.     LPCTSTR lpszWindowName, DWORD dwStyle,
  730.     const RECT& rect,
  731.     CWnd* pParentWnd, UINT nID,
  732.     CCreateContext* pContext)
  733. {
  734.     // can't use for desktop or pop-up windows (use CreateEx instead)
  735.     ASSERT(pParentWnd != NULL);
  736.     ASSERT((dwStyle & WS_POPUP) == 0);
  737.  
  738.     return CreateEx(0, lpszClassName, lpszWindowName,
  739.         dwStyle | WS_CHILD,
  740.         rect.left, rect.top,
  741.         rect.right - rect.left, rect.bottom - rect.top,
  742.         pParentWnd->GetSafeHwnd(), (HMENU)nID, (LPVOID)pContext);
  743. }
  744.  
  745. CWnd::~CWnd()
  746. {
  747.     if (m_hWnd != NULL &&
  748.         this != (CWnd*)&wndTop && this != (CWnd*)&wndBottom &&
  749.         this != (CWnd*)&wndTopMost && this != (CWnd*)&wndNoTopMost)
  750.     {
  751.         TRACE(_T("Warning: calling DestroyWindow in CWnd::~CWnd; ")
  752.            _T("OnDestroy or PostNcDestroy in derived class will not be called.\n"));
  753.         DestroyWindow();
  754.     }
  755.  
  756. #ifndef _AFX_NO_OCC_SUPPORT
  757.     // cleanup control container,
  758.     // including destroying controls
  759.  
  760.     delete m_pCtrlCont;
  761.  
  762.     // cleanup control site
  763.     if (m_pCtrlSite != NULL && m_pCtrlSite->m_pWndCtrl == this)
  764.         m_pCtrlSite->m_pWndCtrl = NULL;
  765. #endif
  766. }
  767.  
  768. void CWnd::OnDestroy()
  769. {
  770. #ifndef _AFX_NO_OCC_SUPPORT
  771.     // cleanup control container
  772.     delete m_pCtrlCont;
  773.     m_pCtrlCont = NULL;
  774. #endif
  775.     Default();
  776. }
  777.  
  778. // WM_NCDESTROY is the absolute LAST message sent.
  779. void CWnd::OnNcDestroy()
  780. {
  781.     // cleanup main and active windows
  782.     CWinThread* pThread = AfxGetThread();
  783.     if (pThread != NULL)
  784.     {
  785.         if (pThread->m_pMainWnd == this)
  786.         {
  787.             if (!afxContextIsDLL)
  788.             {
  789.                 // shut down current thread if possible
  790.                 if (pThread != AfxGetApp() || AfxOleCanExitApp())
  791.                     AfxPostQuitMessage(0);
  792.             }
  793.             pThread->m_pMainWnd = NULL;
  794.         }
  795.         if (pThread->m_pActiveWnd == this)
  796.             pThread->m_pActiveWnd = NULL;
  797.     }
  798.  
  799. #ifndef _AFX_NO_OLE_SUPPORT
  800.     // cleanup OLE drop target interface
  801.     if (m_pDropTarget != NULL)
  802.     {
  803.         m_pDropTarget->Revoke();
  804.         m_pDropTarget = NULL;
  805.     }
  806. #endif
  807.  
  808. #ifndef _AFX_NO_OCC_SUPPORT
  809.     // cleanup control container
  810.     delete m_pCtrlCont;
  811.     m_pCtrlCont = NULL;
  812. #endif
  813.  
  814.     // cleanup tooltip support
  815.     if (m_nFlags & WF_TOOLTIPS)
  816.     {
  817.         CToolTipCtrl* pToolTip = AfxGetThreadState()->m_pToolTip;
  818.         if (pToolTip->GetSafeHwnd() != NULL)
  819.         {
  820.             TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO));
  821.             ti.cbSize = sizeof(AFX_OLDTOOLINFO);
  822.             ti.uFlags = TTF_IDISHWND;
  823.             ti.hwnd = m_hWnd;
  824.             ti.uId = (UINT)m_hWnd;
  825.             pToolTip->SendMessage(TTM_DELTOOL, 0, (LPARAM)&ti);
  826.         }
  827.     }
  828.  
  829.     // call default, unsubclass, and detach from the map
  830.     LONG pfnWndProc = GetWindowLong(m_hWnd, GWL_WNDPROC);
  831.     Default();
  832.     if (GetWindowLong(m_hWnd, GWL_WNDPROC) == pfnWndProc)
  833.     {
  834.         WNDPROC pfnSuper = *GetSuperWndProcAddr();
  835.         if (pfnSuper != NULL)
  836.             SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)pfnSuper);
  837.     }
  838.     Detach();
  839.     ASSERT(m_hWnd == NULL);
  840.  
  841.     // call special post-cleanup routine
  842.     PostNcDestroy();
  843. }
  844.  
  845. void CWnd::PostNcDestroy()
  846. {
  847.     // default to nothing
  848. }
  849.  
  850. void CWnd::OnFinalRelease()
  851. {
  852.     if (m_hWnd != NULL)
  853.         DestroyWindow();    // will call PostNcDestroy
  854.     else
  855.         PostNcDestroy();
  856. }
  857.  
  858. #ifdef _DEBUG
  859. void CWnd::AssertValid() const
  860. {
  861.     if (m_hWnd == NULL)
  862.         return;     // null (unattached) windows are valid
  863.  
  864.     // check for special wnd??? values
  865.     ASSERT(HWND_TOP == NULL);       // same as desktop
  866.     if (m_hWnd == HWND_BOTTOM)
  867.         ASSERT(this == &CWnd::wndBottom);
  868.     else if (m_hWnd == HWND_TOPMOST)
  869.         ASSERT(this == &CWnd::wndTopMost);
  870.     else if (m_hWnd == HWND_NOTOPMOST)
  871.         ASSERT(this == &CWnd::wndNoTopMost);
  872.     else
  873.     {
  874.         // should be a normal window
  875.         ASSERT(::IsWindow(m_hWnd));
  876.  
  877.         // should also be in the permanent or temporary handle map
  878.         CHandleMap* pMap = afxMapHWND();
  879.         ASSERT(pMap != NULL);
  880.  
  881.         CObject* p;
  882.         ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||
  883.             (p = pMap->LookupTemporary(m_hWnd)) != NULL);
  884.         ASSERT((CWnd*)p == this);   // must be us
  885.  
  886.         // Note: if either of the above asserts fire and you are
  887.         // writing a multithreaded application, it is likely that
  888.         // you have passed a C++ object from one thread to another
  889.         // and have used that object in a way that was not intended.
  890.         // (only simple inline wrapper functions should be used)
  891.         //
  892.         // In general, CWnd objects should be passed by HWND from
  893.         // one thread to another.  The receiving thread can wrap
  894.         // the HWND with a CWnd object by using CWnd::FromHandle.
  895.         //
  896.         // It is dangerous to pass C++ objects from one thread to
  897.         // another, unless the objects are designed to be used in
  898.         // such a manner.
  899.     }
  900. }
  901.  
  902. void CWnd::Dump(CDumpContext& dc) const
  903. {
  904.     CObject::Dump(dc);
  905.  
  906.     dc << "\nm_hWnd = " << (UINT)m_hWnd;
  907.  
  908.     if (m_hWnd == NULL || m_hWnd == HWND_BOTTOM ||
  909.         m_hWnd == HWND_TOPMOST || m_hWnd == HWND_NOTOPMOST)
  910.     {
  911.         // not a normal window - nothing more to dump
  912.         return;
  913.     }
  914.  
  915.     if (!::IsWindow(m_hWnd))
  916.     {
  917.         // not a valid window
  918.         dc << " (illegal HWND)";
  919.         return; // don't do anything more
  920.     }
  921.  
  922.     CWnd* pWnd = CWnd::FromHandlePermanent(m_hWnd);
  923.     if (pWnd != this)
  924.         dc << " (Detached or temporary window)";
  925.     else
  926.         dc << " (permanent window)";
  927.  
  928.     // dump out window specific statistics
  929.     TCHAR szBuf [64];
  930.     if (!::SendMessage(m_hWnd, WM_QUERYAFXWNDPROC, 0, 0) && pWnd == this)
  931.         GetWindowText(szBuf, _countof(szBuf));
  932.     else
  933.         ::DefWindowProc(m_hWnd, WM_GETTEXT, _countof(szBuf), (LPARAM)&szBuf[0]);
  934.     dc << "\ncaption = \"" << szBuf << "\"";
  935.  
  936.     ::GetClassName(m_hWnd, szBuf, _countof(szBuf));
  937.     dc << "\nclass name = \"" << szBuf << "\"";
  938.  
  939.     CRect rect;
  940.     GetWindowRect(&rect);
  941.     dc << "\nrect = " << rect;
  942.     dc << "\nparent CWnd* = " << (void*)GetParent();
  943.  
  944.     dc << "\nstyle = " << (void*)::GetWindowLong(m_hWnd, GWL_STYLE);
  945.     if (::GetWindowLong(m_hWnd, GWL_STYLE) & WS_CHILD)
  946.         dc << "\nid = " << _AfxGetDlgCtrlID(m_hWnd);
  947.  
  948.     dc << "\n";
  949. }
  950. #endif
  951.  
  952. BOOL CWnd::DestroyWindow()
  953. {
  954.     if (m_hWnd == NULL)
  955.         return FALSE;
  956.  
  957.     CHandleMap* pMap = afxMapHWND();
  958.     ASSERT(pMap != NULL);
  959.     CWnd* pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd);
  960. #ifdef _DEBUG
  961.     HWND hWndOrig = m_hWnd;
  962. #endif
  963.  
  964. #ifdef _AFX_NO_OCC_SUPPORT
  965.     BOOL bResult = ::DestroyWindow(m_hWnd);
  966. #else //_AFX_NO_OCC_SUPPORT
  967.     BOOL bResult;
  968.     if (m_pCtrlSite == NULL)
  969.         bResult = ::DestroyWindow(m_hWnd);
  970.     else
  971.         bResult = m_pCtrlSite->DestroyControl();
  972. #endif //_AFX_NO_OCC_SUPPORT
  973.  
  974.     // Note that 'this' may have been deleted at this point,
  975.     //  (but only if pWnd != NULL)
  976.     if (pWnd != NULL)
  977.     {
  978.         // Should have been detached by OnNcDestroy
  979. #ifdef _DEBUG
  980.         ASSERT(pMap->LookupPermanent(hWndOrig) == NULL);
  981. #endif
  982.     }
  983.     else
  984.     {
  985. #ifdef _DEBUG
  986.         ASSERT(m_hWnd == hWndOrig);
  987. #endif
  988.         // Detach after DestroyWindow called just in case
  989.         Detach();
  990.     }
  991.     return bResult;
  992. }
  993.  
  994. /////////////////////////////////////////////////////////////////////////////
  995. // Default CWnd implementation
  996.  
  997. LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
  998. {
  999.     if (m_pfnSuper != NULL)
  1000.         return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam);
  1001.  
  1002.     WNDPROC pfnWndProc;
  1003.     if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL)
  1004.         return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam);
  1005.     else
  1006.         return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam);
  1007. }
  1008.  
  1009. WNDPROC* CWnd::GetSuperWndProcAddr()
  1010. {
  1011.     // Note: it is no longer necessary to override GetSuperWndProcAddr
  1012.     //  for each control class with a different WNDCLASS.
  1013.     //  This implementation now uses instance data, such that the previous
  1014.     //  WNDPROC can be anything.
  1015.  
  1016.     return &m_pfnSuper;
  1017. }
  1018.  
  1019. BOOL CWnd::PreTranslateMessage(MSG* pMsg)
  1020. {
  1021.     // handle tooltip messages (some messages cancel, some may cause it to popup)
  1022.     AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  1023.     if (pModuleState->m_pfnFilterToolTipMessage != NULL)
  1024.         (*pModuleState->m_pfnFilterToolTipMessage)(pMsg, this);
  1025.  
  1026.     // no default processing
  1027.     return FALSE;
  1028. }
  1029.  
  1030. void PASCAL CWnd::CancelToolTips(BOOL bKeys)
  1031. {
  1032.     // check for active tooltip
  1033.     _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  1034.     CToolTipCtrl* pToolTip = pThreadState->m_pToolTip;
  1035.     if (pToolTip->GetSafeHwnd() != NULL)
  1036.         pToolTip->SendMessage(TTM_ACTIVATE, FALSE);
  1037.  
  1038.     // check for active control bar fly-by status
  1039.     CControlBar* pLastStatus = pThreadState->m_pLastStatus;
  1040.     if (bKeys && pLastStatus != NULL && GetKeyState(VK_LBUTTON) >= 0)
  1041.         pLastStatus->SetStatusText(-1);
  1042. }
  1043.  
  1044. int CWnd::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
  1045. {
  1046.     // find child window which hits the point
  1047.     // (don't use WindowFromPoint, because it ignores disabled windows)
  1048.     HWND hWndChild = _AfxChildWindowFromPoint(m_hWnd, point);
  1049.     if (hWndChild != NULL)
  1050.     {
  1051.         // return positive hit if control ID isn't -1
  1052.         int nHit = _AfxGetDlgCtrlID(hWndChild);
  1053.  
  1054.         // hits against child windows always center the tip
  1055.         if (pTI != NULL && pTI->cbSize >= sizeof(AFX_OLDTOOLINFO))
  1056.         {
  1057.             // setup the TOOLINFO structure
  1058.             pTI->hwnd = m_hWnd;
  1059.             pTI->uId = (UINT)hWndChild;
  1060.             pTI->uFlags |= TTF_IDISHWND;
  1061.             pTI->lpszText = LPSTR_TEXTCALLBACK;
  1062.  
  1063.             // set TTF_NOTBUTTON and TTF_CENTERTIP if it isn't a button
  1064.             if (!(::SendMessage(hWndChild, WM_GETDLGCODE, 0, 0) & DLGC_BUTTON))
  1065.                 pTI->uFlags |= TTF_NOTBUTTON|TTF_CENTERTIP;
  1066.         }
  1067.         return nHit;
  1068.     }
  1069.     return -1;  // not found
  1070. }
  1071.  
  1072. void CWnd::GetWindowText(CString& rString) const
  1073. {
  1074.     ASSERT(::IsWindow(m_hWnd));
  1075.  
  1076. #ifndef _AFX_NO_OCC_SUPPORT
  1077.     if (m_pCtrlSite == NULL)
  1078.     {
  1079. #endif
  1080.         int nLen = ::GetWindowTextLength(m_hWnd);
  1081.         ::GetWindowText(m_hWnd, rString.GetBufferSetLength(nLen), nLen+1);
  1082.         rString.ReleaseBuffer();
  1083.  
  1084. #ifndef _AFX_NO_OCC_SUPPORT
  1085.     }
  1086.     else
  1087.     {
  1088.         m_pCtrlSite->GetWindowText(rString);
  1089.     }
  1090. #endif
  1091. }
  1092.  
  1093. int CWnd::GetDlgItemText(int nID, CString& rString) const
  1094. {
  1095.     ASSERT(::IsWindow(m_hWnd));
  1096.     rString = &afxChNil;    // empty without deallocating
  1097.  
  1098. #ifndef _AFX_NO_OCC_SUPPORT
  1099.     if (m_pCtrlCont == NULL)
  1100.     {
  1101. #endif
  1102.         HWND hWnd = ::GetDlgItem(m_hWnd, nID);
  1103.         if (hWnd != NULL)
  1104.         {
  1105.             int nLen = ::GetWindowTextLength(hWnd);
  1106.             ::GetWindowText(hWnd, rString.GetBufferSetLength(nLen), nLen+1);
  1107.             rString.ReleaseBuffer();
  1108.         }
  1109.  
  1110. #ifndef _AFX_NO_OCC_SUPPORT
  1111.     }
  1112.     else
  1113.     {
  1114.         CWnd* pWnd = GetDlgItem(nID);
  1115.         if (pWnd != NULL)
  1116.             pWnd->GetWindowText(rString);
  1117.     }
  1118. #endif
  1119.  
  1120.     return rString.GetLength();
  1121. }
  1122.  
  1123. BOOL CWnd::GetWindowPlacement(WINDOWPLACEMENT* lpwndpl) const
  1124. {
  1125.     ASSERT(::IsWindow(m_hWnd));
  1126.     lpwndpl->length = sizeof(WINDOWPLACEMENT);
  1127.     return ::GetWindowPlacement(m_hWnd, lpwndpl);
  1128. }
  1129.  
  1130. BOOL CWnd::SetWindowPlacement(const WINDOWPLACEMENT* lpwndpl)
  1131. {
  1132.     ASSERT(::IsWindow(m_hWnd));
  1133.     ((WINDOWPLACEMENT*)lpwndpl)->length = sizeof(WINDOWPLACEMENT);
  1134.     return ::SetWindowPlacement(m_hWnd, lpwndpl);
  1135. }
  1136.  
  1137. /////////////////////////////////////////////////////////////////////////////
  1138. // CWnd will delegate owner draw messages to self drawing controls
  1139.  
  1140. // Drawing: for all 4 control types
  1141. void CWnd::OnDrawItem(int /*nIDCtl*/, LPDRAWITEMSTRUCT lpDrawItemStruct)
  1142. {
  1143.     if (lpDrawItemStruct->CtlType == ODT_MENU)
  1144.     {
  1145.         CMenu* pMenu = CMenu::FromHandlePermanent(
  1146.             (HMENU)lpDrawItemStruct->hwndItem);
  1147.         if (pMenu != NULL)
  1148.         {
  1149.             pMenu->DrawItem(lpDrawItemStruct);
  1150.             return; // eat it
  1151.         }
  1152.     }
  1153.     else
  1154.     {
  1155.         // reflect notification to child window control
  1156.         if (ReflectLastMsg(lpDrawItemStruct->hwndItem))
  1157.             return;     // eat it
  1158.     }
  1159.     // not handled - do default
  1160.     Default();
  1161. }
  1162.  
  1163. // Drawing: for all 4 control types
  1164. int CWnd::OnCompareItem(int /*nIDCtl*/, LPCOMPAREITEMSTRUCT lpCompareItemStruct)
  1165. {
  1166.     // reflect notification to child window control
  1167.     LRESULT lResult;
  1168.     if (ReflectLastMsg(lpCompareItemStruct->hwndItem, &lResult))
  1169.         return (int)lResult;        // eat it
  1170.  
  1171.     // not handled - do default
  1172.     return (int)Default();
  1173. }
  1174.  
  1175. void CWnd::OnDeleteItem(int /*nIDCtl*/, LPDELETEITEMSTRUCT lpDeleteItemStruct)
  1176. {
  1177.     // reflect notification to child window control
  1178.     if (ReflectLastMsg(lpDeleteItemStruct->hwndItem))
  1179.         return;     // eat it
  1180.     // not handled - do default
  1181.     Default();
  1182. }
  1183.  
  1184. int CWnd::OnCharToItem(UINT, CListBox* pWnd, UINT)
  1185. {
  1186.     if (pWnd != NULL)
  1187.     {
  1188.         LRESULT lResult;
  1189.         if (pWnd->SendChildNotifyLastMsg(&lResult))
  1190.             return (int)lResult;     // eat it
  1191.     }
  1192.     // not handled - do default
  1193.     return (int)Default();
  1194. }
  1195.  
  1196. int CWnd::OnVKeyToItem(UINT, CListBox* pWnd, UINT)
  1197. {
  1198.     if (pWnd != NULL)
  1199.     {
  1200.         LRESULT lResult;
  1201.         if (pWnd->SendChildNotifyLastMsg(&lResult))
  1202.             return (int)lResult;     // eat it
  1203.     }
  1204.     // not handled - do default
  1205.     return (int)Default();
  1206. }
  1207.  
  1208. /////////////////////////////////////////////////////////////////////////////
  1209. // Self drawing menus are a little trickier
  1210.  
  1211. BOOL CMenu::TrackPopupMenu(UINT nFlags, int x, int y,
  1212.         CWnd* pWnd, LPCRECT lpRect)
  1213. {
  1214.     ASSERT(m_hMenu != NULL);
  1215.  
  1216.     _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  1217.     HWND hWndOld = pThreadState->m_hTrackingWindow;
  1218.     HMENU hMenuOld = pThreadState->m_hTrackingMenu;
  1219.     pThreadState->m_hTrackingWindow = pWnd->GetSafeHwnd();
  1220.     pThreadState->m_hTrackingMenu = m_hMenu;
  1221.     BOOL bOK = ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0,
  1222.             pThreadState->m_hTrackingWindow, lpRect);
  1223.     pThreadState->m_hTrackingWindow = hWndOld;
  1224.     pThreadState->m_hTrackingMenu = hMenuOld;
  1225.  
  1226.     return bOK;
  1227. }
  1228.  
  1229. AFX_STATIC CMenu* AFXAPI _AfxFindPopupMenuFromID(CMenu* pMenu, UINT nID)
  1230. {
  1231.     ASSERT_VALID(pMenu);
  1232.     // walk through all items, looking for ID match
  1233.     UINT nItems = pMenu->GetMenuItemCount();
  1234.     for (int iItem = 0; iItem < (int)nItems; iItem++)
  1235.     {
  1236.         CMenu* pPopup = pMenu->GetSubMenu(iItem);
  1237.         if (pPopup != NULL)
  1238.         {
  1239.             // recurse to child popup
  1240.             pPopup = _AfxFindPopupMenuFromID(pPopup, nID);
  1241.             // check popups on this popup
  1242.             if (pPopup != NULL)
  1243.                 return pPopup;
  1244.         }
  1245.         else if (pMenu->GetMenuItemID(iItem) == nID)
  1246.         {
  1247.             // it is a normal item inside our popup
  1248.             pMenu = CMenu::FromHandlePermanent(pMenu->m_hMenu);
  1249.             return pMenu;
  1250.         }
  1251.     }
  1252.     // not found
  1253.     return NULL;
  1254. }
  1255.  
  1256. // Measure item implementation relies on unique control/menu IDs
  1257. void CWnd::OnMeasureItem(int /*nIDCtl*/, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  1258. {
  1259.     if (lpMeasureItemStruct->CtlType == ODT_MENU)
  1260.     {
  1261.         ASSERT(lpMeasureItemStruct->CtlID == 0);
  1262.         CMenu* pMenu;
  1263.  
  1264.         _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  1265.         if (pThreadState->m_hTrackingWindow == m_hWnd)
  1266.         {
  1267.             // start from popup
  1268.             pMenu = CMenu::FromHandle(pThreadState->m_hTrackingMenu);
  1269.         }
  1270.         else
  1271.         {
  1272.             // start from menubar
  1273.             pMenu = GetMenu();
  1274.         }
  1275.  
  1276.         pMenu = _AfxFindPopupMenuFromID(pMenu, lpMeasureItemStruct->itemID);
  1277.         if (pMenu != NULL)
  1278.             pMenu->MeasureItem(lpMeasureItemStruct);
  1279.         else
  1280.             TRACE1("Warning: unknown WM_MEASUREITEM for menu item 0x%04X.\n",
  1281.                 lpMeasureItemStruct->itemID);
  1282.     }
  1283.     else
  1284.     {
  1285.         CWnd* pChild = GetDescendantWindow(lpMeasureItemStruct->CtlID, TRUE);
  1286.         if (pChild != NULL && pChild->SendChildNotifyLastMsg())
  1287.             return;     // eaten by child
  1288.     }
  1289.     // not handled - do default
  1290.     Default();
  1291. }
  1292.  
  1293. /////////////////////////////////////////////////////////////////////////////
  1294. // Additional helpers for WNDCLASS init
  1295.  
  1296. // like RegisterClass, except will automatically call UnregisterClass
  1297. BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)
  1298. {
  1299.     WNDCLASS wndcls;
  1300.     if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,
  1301.         &wndcls))
  1302.     {
  1303.         // class already registered
  1304.         return TRUE;
  1305.     }
  1306.  
  1307.     if (!::RegisterClass(lpWndClass))
  1308.     {
  1309.         TRACE1("Can't register window class named %s\n",
  1310.             lpWndClass->lpszClassName);
  1311.         return FALSE;
  1312.     }
  1313.  
  1314.     if (afxContextIsDLL)
  1315.     {
  1316.         AfxLockGlobals(CRIT_REGCLASSLIST);
  1317.         TRY
  1318.         {
  1319.             // class registered successfully, add to registered list
  1320.             AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  1321.             LPTSTR lpszUnregisterList = pModuleState->m_szUnregisterList;
  1322.             // the buffer is of fixed size -- ensure that it does not overflow
  1323.             ASSERT(lstrlen(lpszUnregisterList) + 1 +
  1324.                 lstrlen(lpWndClass->lpszClassName) + 1 <
  1325.                 _countof(pModuleState->m_szUnregisterList));
  1326.             // append classname + newline to m_szUnregisterList
  1327.             lstrcat(lpszUnregisterList, lpWndClass->lpszClassName);
  1328.             TCHAR szTemp[2];
  1329.             szTemp[0] = '\n';
  1330.             szTemp[1] = '\0';
  1331.             lstrcat(lpszUnregisterList, szTemp);
  1332.         }
  1333.         CATCH_ALL(e)
  1334.         {
  1335.             AfxUnlockGlobals(CRIT_REGCLASSLIST);
  1336.             THROW_LAST();
  1337.             // Note: DELETE_EXCEPTION not required.
  1338.         }
  1339.         END_CATCH_ALL
  1340.         AfxUnlockGlobals(CRIT_REGCLASSLIST);
  1341.     }
  1342.  
  1343.     return TRUE;
  1344. }
  1345.  
  1346. LPCTSTR AFXAPI AfxRegisterWndClass(UINT nClassStyle,
  1347.     HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon)
  1348. {
  1349.     // Returns a temporary string name for the class
  1350.     //  Save in a CString if you want to use it for a long time
  1351.     LPTSTR lpszName = AfxGetThreadState()->m_szTempClassName;
  1352.  
  1353.     // generate a synthetic name for this class
  1354.     HINSTANCE hInst = AfxGetInstanceHandle();
  1355.     if (hCursor == NULL && hbrBackground == NULL && hIcon == NULL)
  1356.         wsprintf(lpszName, _T("Afx:%x:%x"), (UINT)hInst, nClassStyle);
  1357.     else
  1358.         wsprintf(lpszName, _T("Afx:%x:%x:%x:%x:%x"), (UINT)hInst, nClassStyle,
  1359.             (UINT)hCursor, (UINT)hbrBackground, (UINT)hIcon);
  1360.  
  1361.     // see if the class already exists
  1362.     WNDCLASS wndcls;
  1363.     if (::GetClassInfo(hInst, lpszName, &wndcls))
  1364.     {
  1365.         // already registered, assert everything is good
  1366.         ASSERT(wndcls.style == nClassStyle);
  1367.  
  1368.         // NOTE: We have to trust that the hIcon, hbrBackground, and the
  1369.         //  hCursor are semantically the same, because sometimes Windows does
  1370.         //  some internal translation or copying of those handles before
  1371.         //  storing them in the internal WNDCLASS retrieved by GetClassInfo.
  1372.         return lpszName;
  1373.     }
  1374.  
  1375.     // otherwise we need to register a new class
  1376.     wndcls.style = nClassStyle;
  1377.     wndcls.lpfnWndProc = DefWindowProc;
  1378.     wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
  1379.     wndcls.hInstance = hInst;
  1380.     wndcls.hIcon = hIcon;
  1381.     wndcls.hCursor = hCursor;
  1382.     wndcls.hbrBackground = hbrBackground;
  1383.     wndcls.lpszMenuName = NULL;
  1384.     wndcls.lpszClassName = lpszName;
  1385.     if (!AfxRegisterClass(&wndcls))
  1386.         AfxThrowResourceException();
  1387.  
  1388.     // return thread-local pointer
  1389.     return lpszName;
  1390. }
  1391.  
  1392. struct AFX_CTLCOLOR
  1393. {
  1394.     HWND hWnd;
  1395.     HDC hDC;
  1396.     UINT nCtlType;
  1397. };
  1398.  
  1399. LRESULT CWnd::OnNTCtlColor(WPARAM wParam, LPARAM lParam)
  1400. {
  1401.     // fill in special struct for compatiblity with 16-bit WM_CTLCOLOR
  1402.     AFX_CTLCOLOR ctl;
  1403.     ctl.hDC = (HDC)wParam;
  1404.     ctl.hWnd = (HWND)lParam;
  1405.     _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  1406.     ctl.nCtlType = pThreadState->m_lastSentMsg.message - WM_CTLCOLORMSGBOX;
  1407.     ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX);
  1408.     ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC);
  1409.  
  1410.     // Note: We call the virtual WindowProc for this window directly,
  1411.     //  instead of calling AfxCallWindowProc, so that Default()
  1412.     //  will still work (it will call the Default window proc with
  1413.     //  the original Win32 WM_CTLCOLOR message).
  1414.     return WindowProc(WM_CTLCOLOR, 0, (LPARAM)&ctl);
  1415. }
  1416.  
  1417. /////////////////////////////////////////////////////////////////////////////
  1418. // CWnd extensions for help support
  1419.  
  1420. void CWnd::WinHelp(DWORD dwData, UINT nCmd)
  1421. {
  1422.     CWinApp* pApp = AfxGetApp();
  1423.     ASSERT_VALID(pApp);
  1424.     ASSERT(pApp->m_pszHelpFilePath != NULL);
  1425.  
  1426.     CWaitCursor wait;
  1427.     if (IsFrameWnd())
  1428.     {
  1429.         // CFrameWnd windows should be allowed to exit help mode first
  1430.         CFrameWnd* pFrameWnd = (CFrameWnd*)this;
  1431.         pFrameWnd->ExitHelpMode();
  1432.     }
  1433.  
  1434.     // cancel any tracking modes
  1435.     SendMessage(WM_CANCELMODE);
  1436.     SendMessageToDescendants(WM_CANCELMODE, 0, 0, TRUE, TRUE);
  1437.  
  1438.     // need to use top level parent (for the case where m_hWnd is in DLL)
  1439.     CWnd* pWnd = GetTopLevelParent();
  1440.     pWnd->SendMessage(WM_CANCELMODE);
  1441.     pWnd->SendMessageToDescendants(WM_CANCELMODE, 0, 0, TRUE, TRUE);
  1442.  
  1443.     // attempt to cancel capture
  1444.     HWND hWndCapture = ::GetCapture();
  1445.     if (hWndCapture != NULL)
  1446.         ::SendMessage(hWndCapture, WM_CANCELMODE, 0, 0);
  1447.  
  1448.     TRACE3("WinHelp: pszHelpFile = '%s', dwData: $%lx, fuCommand: %d.\n",
  1449.         pApp->m_pszHelpFilePath, dwData, nCmd);
  1450.  
  1451.     // finally, run the Windows Help engine
  1452.     if (!::WinHelp(pWnd->m_hWnd, pApp->m_pszHelpFilePath, nCmd, dwData))
  1453.         AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH_HELP);
  1454. }
  1455.  
  1456. /////////////////////////////////////////////////////////////////////////////
  1457. // Message table implementation
  1458.  
  1459. BEGIN_MESSAGE_MAP(CWnd, CCmdTarget)
  1460.     ON_MESSAGE(WM_CTLCOLORSTATIC, OnNTCtlColor)
  1461.     ON_MESSAGE(WM_CTLCOLOREDIT, OnNTCtlColor)
  1462.     ON_MESSAGE(WM_CTLCOLORBTN, OnNTCtlColor)
  1463.     ON_MESSAGE(WM_CTLCOLORLISTBOX, OnNTCtlColor)
  1464.     ON_MESSAGE(WM_CTLCOLORDLG, OnNTCtlColor)
  1465.     ON_MESSAGE(WM_CTLCOLORMSGBOX, OnNTCtlColor)
  1466.     ON_MESSAGE(WM_CTLCOLORSCROLLBAR, OnNTCtlColor)
  1467.     //{{AFX_MSG_MAP(CWnd)
  1468.     ON_WM_DRAWITEM()
  1469.     ON_WM_MEASUREITEM()
  1470.     ON_WM_CTLCOLOR()
  1471.     ON_WM_COMPAREITEM()
  1472.     ON_WM_ENTERIDLE()
  1473.     ON_WM_HSCROLL()
  1474.     ON_WM_VSCROLL()
  1475.     ON_WM_DELETEITEM()
  1476.     ON_WM_CHARTOITEM()
  1477.     ON_WM_VKEYTOITEM()
  1478.     ON_WM_NCDESTROY()
  1479.     ON_WM_PARENTNOTIFY()
  1480.     ON_WM_SYSCOLORCHANGE()
  1481.     ON_WM_DEVMODECHANGE()
  1482.     ON_WM_HELPINFO()
  1483.     ON_WM_SETTINGCHANGE()
  1484.     //}}AFX_MSG_MAP
  1485. #ifndef _AFX_NO_OCC_SUPPORT
  1486.     ON_WM_DESTROY()
  1487. #endif
  1488.     ON_MESSAGE(WM_ACTIVATETOPLEVEL, OnActivateTopLevel)
  1489.     ON_MESSAGE(WM_DISPLAYCHANGE, OnDisplayChange)
  1490.     ON_REGISTERED_MESSAGE(CWnd::m_nMsgDragList, OnDragList)
  1491. END_MESSAGE_MAP()
  1492.  
  1493. /////////////////////////////////////////////////////////////////////////////
  1494. // Routines for fast search of message maps
  1495.  
  1496. const AFX_MSGMAP_ENTRY* AFXAPI
  1497. AfxFindMessageEntry(const AFX_MSGMAP_ENTRY* lpEntry,
  1498.     UINT nMsg, UINT nCode, UINT nID)
  1499. {
  1500. #if defined(_M_IX86) && !defined(_AFX_PORTABLE)
  1501. // 32-bit Intel 386/486 version.
  1502.  
  1503.     ASSERT(offsetof(AFX_MSGMAP_ENTRY, nMessage) == 0);
  1504.     ASSERT(offsetof(AFX_MSGMAP_ENTRY, nCode) == 4);
  1505.     ASSERT(offsetof(AFX_MSGMAP_ENTRY, nID) == 8);
  1506.     ASSERT(offsetof(AFX_MSGMAP_ENTRY, nLastID) == 12);
  1507.     ASSERT(offsetof(AFX_MSGMAP_ENTRY, nSig) == 16);
  1508.  
  1509.     _asm
  1510.     {
  1511.             MOV     EBX,lpEntry
  1512.             MOV     EAX,nMsg
  1513.             MOV     EDX,nCode
  1514.             MOV     ECX,nID
  1515.     __loop:
  1516.             CMP     DWORD PTR [EBX+16],0        ; nSig (0 => end)
  1517.             JZ      __failed
  1518.             CMP     EAX,DWORD PTR [EBX]         ; nMessage
  1519.             JE      __found_message
  1520.     __next:
  1521.             ADD     EBX,SIZE AFX_MSGMAP_ENTRY
  1522.             JMP     short __loop
  1523.     __found_message:
  1524.             CMP     EDX,DWORD PTR [EBX+4]       ; nCode
  1525.             JNE     __next
  1526.     // message and code good so far
  1527.     // check the ID
  1528.             CMP     ECX,DWORD PTR [EBX+8]       ; nID
  1529.             JB      __next
  1530.             CMP     ECX,DWORD PTR [EBX+12]      ; nLastID
  1531.             JA      __next
  1532.     // found a match
  1533.             MOV     lpEntry,EBX                 ; return EBX
  1534.             JMP     short __end
  1535.     __failed:
  1536.             XOR     EAX,EAX                     ; return NULL
  1537.             MOV     lpEntry,EAX
  1538.     __end:
  1539.     }
  1540.     return lpEntry;
  1541. #else  // _AFX_PORTABLE
  1542.     // C version of search routine
  1543.     while (lpEntry->nSig != AfxSig_end)
  1544.     {
  1545.         if (lpEntry->nMessage == nMsg && lpEntry->nCode == nCode &&
  1546.             nID >= lpEntry->nID && nID <= lpEntry->nLastID)
  1547.         {
  1548.             return lpEntry;
  1549.         }
  1550.         lpEntry++;
  1551.     }
  1552.     return NULL;    // not found
  1553. #endif  // _AFX_PORTABLE
  1554. }
  1555.  
  1556. /////////////////////////////////////////////////////////////////////////////
  1557. // Cache of most recently sent messages
  1558.  
  1559. #ifndef iHashMax
  1560. // iHashMax must be a power of two
  1561.     #define iHashMax 512
  1562. #endif
  1563.  
  1564. struct AFX_MSG_CACHE
  1565. {
  1566.     UINT nMsg;
  1567.     const AFX_MSGMAP_ENTRY* lpEntry;
  1568.     const AFX_MSGMAP* pMessageMap;
  1569. };
  1570.  
  1571. AFX_MSG_CACHE _afxMsgCache[iHashMax];
  1572.  
  1573. void AFXAPI AfxResetMsgCache()
  1574. {
  1575.     memset(_afxMsgCache, 0, sizeof(_afxMsgCache));
  1576. }
  1577.  
  1578. /////////////////////////////////////////////////////////////////////////////
  1579. // main WindowProc implementation
  1580.  
  1581. LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  1582. {
  1583.     // OnWndMsg does most of the work, except for DefWindowProc call
  1584.     LRESULT lResult = 0;
  1585.     if (!OnWndMsg(message, wParam, lParam, &lResult))
  1586.         lResult = DefWindowProc(message, wParam, lParam);
  1587.     return lResult;
  1588. }
  1589.  
  1590. BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  1591. {
  1592.     LRESULT lResult = 0;
  1593.  
  1594.     // special case for commands
  1595.     if (message == WM_COMMAND)
  1596.     {
  1597.         if (OnCommand(wParam, lParam))
  1598.         {
  1599.             lResult = 1;
  1600.             goto LReturnTrue;
  1601.         }
  1602.         return FALSE;
  1603.     }
  1604.  
  1605.     // special case for notifies
  1606.     if (message == WM_NOTIFY)
  1607.     {
  1608.         NMHDR* pNMHDR = (NMHDR*)lParam;
  1609.         if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
  1610.             goto LReturnTrue;
  1611.         return FALSE;
  1612.     }
  1613.  
  1614.     // special case for activation
  1615.     if (message == WM_ACTIVATE)
  1616.         _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));
  1617.  
  1618.     // special case for set cursor HTERROR
  1619.     if (message == WM_SETCURSOR &&
  1620.         _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
  1621.     {
  1622.         lResult = 1;
  1623.         goto LReturnTrue;
  1624.     }
  1625.  
  1626.     const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
  1627.     UINT iHash; iHash = (LOWORD((DWORD)pMessageMap) ^ message) & (iHashMax-1);
  1628.     AfxLockGlobals(CRIT_WINMSGCACHE);
  1629.     AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];
  1630.     const AFX_MSGMAP_ENTRY* lpEntry;
  1631.     if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)
  1632.     {
  1633.         // cache hit
  1634.         lpEntry = pMsgCache->lpEntry;
  1635.         AfxUnlockGlobals(CRIT_WINMSGCACHE);
  1636.         if (lpEntry == NULL)
  1637.             return FALSE;
  1638.  
  1639.         // cache hit, and it needs to be handled
  1640.         if (message < 0xC000)
  1641.             goto LDispatch;
  1642.         else
  1643.             goto LDispatchRegistered;
  1644.     }
  1645.     else
  1646.     {
  1647.         // not in cache, look for it
  1648.         pMsgCache->nMsg = message;
  1649.         pMsgCache->pMessageMap = pMessageMap;
  1650.  
  1651. #ifdef _AFXDLL
  1652.         for (/* pMessageMap already init'ed */; pMessageMap != NULL;
  1653.             pMessageMap = (*pMessageMap->pfnGetBaseMap)())
  1654. #else
  1655.         for (/* pMessageMap already init'ed */; pMessageMap != NULL;
  1656.             pMessageMap = pMessageMap->pBaseMap)
  1657. #endif
  1658.         {
  1659.             // Note: catch not so common but fatal mistake!!
  1660.             //      BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)
  1661. #ifdef _AFXDLL
  1662.             ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
  1663. #else
  1664.             ASSERT(pMessageMap != pMessageMap->pBaseMap);
  1665. #endif
  1666.  
  1667.             if (message < 0xC000)
  1668.             {
  1669.                 // constant window message
  1670.                 if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
  1671.                     message, 0, 0)) != NULL)
  1672.                 {
  1673.                     pMsgCache->lpEntry = lpEntry;
  1674.                     AfxUnlockGlobals(CRIT_WINMSGCACHE);
  1675.                     goto LDispatch;
  1676.                 }
  1677.             }
  1678.             else
  1679.             {
  1680.                 // registered windows message
  1681.                 lpEntry = pMessageMap->lpEntries;
  1682.                 while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
  1683.                 {
  1684.                     UINT* pnID = (UINT*)(lpEntry->nSig);
  1685.                     ASSERT(*pnID >= 0xC000 || *pnID == 0);
  1686.                         // must be successfully registered
  1687.                     if (*pnID == message)
  1688.                     {
  1689.                         pMsgCache->lpEntry = lpEntry;
  1690.                         AfxUnlockGlobals(CRIT_WINMSGCACHE);
  1691.                         goto LDispatchRegistered;
  1692.                     }
  1693.                     lpEntry++;      // keep looking past this one
  1694.                 }
  1695.             }
  1696.         }
  1697.  
  1698.         pMsgCache->lpEntry = NULL;
  1699.         AfxUnlockGlobals(CRIT_WINMSGCACHE);
  1700.         return FALSE;
  1701.     }
  1702.     ASSERT(FALSE);      // not reached
  1703.  
  1704. LDispatch:
  1705.     ASSERT(message < 0xC000);
  1706.     union MessageMapFunctions mmf;
  1707.     mmf.pfn = lpEntry->pfn;
  1708.  
  1709.     // if we've got WM_SETTINGCHANGE / WM_WININICHANGE, we need to
  1710.     // decide if we're going to call OnWinIniChange() or OnSettingChange()
  1711.  
  1712.     int nSig;
  1713.     nSig = lpEntry->nSig;
  1714.     if (lpEntry->nID == WM_SETTINGCHANGE)
  1715.     {
  1716.         DWORD dwVersion = GetVersion();
  1717.         if (LOBYTE(LOWORD(dwVersion)) >= 4)
  1718.             nSig = AfxSig_vws;
  1719.         else
  1720.             nSig = AfxSig_vs;
  1721.     }
  1722.  
  1723.     switch (nSig)
  1724.     {
  1725.     default:
  1726.         ASSERT(FALSE);
  1727.         break;
  1728.  
  1729.     case AfxSig_bD:
  1730.         lResult = (this->*mmf.pfn_bD)(CDC::FromHandle((HDC)wParam));
  1731.         break;
  1732.  
  1733.     case AfxSig_bb:     // AfxSig_bb, AfxSig_bw, AfxSig_bh
  1734.         lResult = (this->*mmf.pfn_bb)((BOOL)wParam);
  1735.         break;
  1736.  
  1737.     case AfxSig_bWww:   // really AfxSig_bWiw
  1738.         lResult = (this->*mmf.pfn_bWww)(CWnd::FromHandle((HWND)wParam),
  1739.             (short)LOWORD(lParam), HIWORD(lParam));
  1740.         break;
  1741.  
  1742.     case AfxSig_bWCDS:
  1743.         lResult = (this->*mmf.pfn_bWCDS)(CWnd::FromHandle((HWND)wParam),
  1744.             (COPYDATASTRUCT*)lParam);
  1745.         break;
  1746.  
  1747.     case AfxSig_bHELPINFO:
  1748.         lResult = (this->*mmf.pfn_bHELPINFO)((HELPINFO*)lParam);
  1749.         break;
  1750.  
  1751.     case AfxSig_hDWw:
  1752.         {
  1753.             // special case for OnCtlColor to avoid too many temporary objects
  1754.             ASSERT(message == WM_CTLCOLOR);
  1755.             AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
  1756.             CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
  1757.             CWnd wndTemp; wndTemp.m_hWnd = pCtl->hWnd;
  1758.             UINT nCtlType = pCtl->nCtlType;
  1759.             // if not coming from a permanent window, use stack temporary
  1760.             CWnd* pWnd = CWnd::FromHandlePermanent(wndTemp.m_hWnd);
  1761.             if (pWnd == NULL)
  1762.             {
  1763. #ifndef _AFX_NO_OCC_SUPPORT
  1764.                 // determine the site of the OLE control if it is one
  1765.                 COleControlSite* pSite;
  1766.                 if (m_pCtrlCont != NULL && (pSite = (COleControlSite*)
  1767.                     m_pCtrlCont->m_siteMap.GetValueAt(wndTemp.m_hWnd)) != NULL)
  1768.                 {
  1769.                     wndTemp.m_pCtrlSite = pSite;
  1770.                 }
  1771. #endif
  1772.                 pWnd = &wndTemp;
  1773.             }
  1774.             HBRUSH hbr = (this->*mmf.pfn_hDWw)(&dcTemp, pWnd, nCtlType);
  1775.             // fast detach of temporary objects
  1776.             dcTemp.m_hDC = NULL;
  1777.             wndTemp.m_hWnd = NULL;
  1778.             lResult = (LRESULT)hbr;
  1779.         }
  1780.         break;
  1781.  
  1782.     case AfxSig_hDw:
  1783.         {
  1784.             // special case for CtlColor to avoid too many temporary objects
  1785.             ASSERT(message == WM_REFLECT_BASE+WM_CTLCOLOR);
  1786.             AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
  1787.             CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
  1788.             UINT nCtlType = pCtl->nCtlType;
  1789.             HBRUSH hbr = (this->*mmf.pfn_hDw)(&dcTemp, nCtlType);
  1790.             // fast detach of temporary objects
  1791.             dcTemp.m_hDC = NULL;
  1792.             lResult = (LRESULT)hbr;
  1793.         }
  1794.         break;
  1795.  
  1796.     case AfxSig_iwWw:
  1797.         lResult = (this->*mmf.pfn_iwWw)(LOWORD(wParam),
  1798.             CWnd::FromHandle((HWND)lParam), HIWORD(wParam));
  1799.         break;
  1800.  
  1801.     case AfxSig_iww:
  1802.         lResult = (this->*mmf.pfn_iww)(LOWORD(wParam), HIWORD(wParam));
  1803.         break;
  1804.  
  1805.     case AfxSig_iWww:   // really AfxSig_iWiw
  1806.         lResult = (this->*mmf.pfn_iWww)(CWnd::FromHandle((HWND)wParam),
  1807.             (short)LOWORD(lParam), HIWORD(lParam));
  1808.         break;
  1809.  
  1810.     case AfxSig_is:
  1811.         lResult = (this->*mmf.pfn_is)((LPTSTR)lParam);
  1812.         break;
  1813.  
  1814.     case AfxSig_lwl:
  1815.         lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
  1816.         break;
  1817.  
  1818.     case AfxSig_lwwM:
  1819.         lResult = (this->*mmf.pfn_lwwM)((UINT)LOWORD(wParam),
  1820.             (UINT)HIWORD(wParam), (CMenu*)CMenu::FromHandle((HMENU)lParam));
  1821.         break;
  1822.  
  1823.     case AfxSig_vv:
  1824.         (this->*mmf.pfn_vv)();
  1825.         break;
  1826.  
  1827.     case AfxSig_vw: // AfxSig_vb, AfxSig_vh
  1828.         (this->*mmf.pfn_vw)(wParam);
  1829.         break;
  1830.  
  1831.     case AfxSig_vww:
  1832.         (this->*mmf.pfn_vww)((UINT)wParam, (UINT)lParam);
  1833.         break;
  1834.  
  1835.     case AfxSig_vvii:
  1836.         (this->*mmf.pfn_vvii)((short)LOWORD(lParam), (short)HIWORD(lParam));
  1837.         break;
  1838.  
  1839.     case AfxSig_vwww:
  1840.         (this->*mmf.pfn_vwww)(wParam, LOWORD(lParam), HIWORD(lParam));
  1841.         break;
  1842.  
  1843.     case AfxSig_vwii:
  1844.         (this->*mmf.pfn_vwii)(wParam, LOWORD(lParam), HIWORD(lParam));
  1845.         break;
  1846.  
  1847.     case AfxSig_vwl:
  1848.         (this->*mmf.pfn_vwl)(wParam, lParam);
  1849.         break;
  1850.  
  1851.     case AfxSig_vbWW:
  1852.         (this->*mmf.pfn_vbWW)(m_hWnd == (HWND)lParam,
  1853.             CWnd::FromHandle((HWND)lParam),
  1854.             CWnd::FromHandle((HWND)wParam));
  1855.         break;
  1856.  
  1857.     case AfxSig_vD:
  1858.         (this->*mmf.pfn_vD)(CDC::FromHandle((HDC)wParam));
  1859.         break;
  1860.  
  1861.     case AfxSig_vM:
  1862.         (this->*mmf.pfn_vM)(CMenu::FromHandle((HMENU)wParam));
  1863.         break;
  1864.  
  1865.     case AfxSig_vMwb:
  1866.         (this->*mmf.pfn_vMwb)(CMenu::FromHandle((HMENU)wParam),
  1867.             LOWORD(lParam), (BOOL)HIWORD(lParam));
  1868.         break;
  1869.  
  1870.     case AfxSig_vW:
  1871.         (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)wParam));
  1872.         break;
  1873.  
  1874.     case AfxSig_vW2:
  1875.         (this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)lParam));
  1876.         break;
  1877.  
  1878.     case AfxSig_vWww:
  1879.         (this->*mmf.pfn_vWww)(CWnd::FromHandle((HWND)wParam), LOWORD(lParam),
  1880.             HIWORD(lParam));
  1881.         break;
  1882.  
  1883.     case AfxSig_vWp:
  1884.         {
  1885.             CPoint point((DWORD)lParam);
  1886.             (this->*mmf.pfn_vWp)(CWnd::FromHandle((HWND)wParam), point);
  1887.         }
  1888.         break;
  1889.  
  1890.     case AfxSig_vWh:
  1891.         (this->*mmf.pfn_vWh)(CWnd::FromHandle((HWND)wParam),
  1892.                 (HANDLE)lParam);
  1893.         break;
  1894.  
  1895.     case AfxSig_vwW:
  1896.         (this->*mmf.pfn_vwW)(wParam, CWnd::FromHandle((HWND)lParam));
  1897.         break;
  1898.  
  1899.     case AfxSig_vwWb:
  1900.         (this->*mmf.pfn_vwWb)((UINT)(LOWORD(wParam)),
  1901.             CWnd::FromHandle((HWND)lParam), (BOOL)HIWORD(wParam));
  1902.         break;
  1903.  
  1904.     case AfxSig_vwwW:
  1905.     case AfxSig_vwwx:
  1906.         {
  1907.             // special case for WM_VSCROLL and WM_HSCROLL
  1908.             ASSERT(message == WM_VSCROLL || message == WM_HSCROLL ||
  1909.                 message == WM_VSCROLL+WM_REFLECT_BASE || message == WM_HSCROLL+WM_REFLECT_BASE);
  1910.             int nScrollCode = (short)LOWORD(wParam);
  1911.             int nPos = (short)HIWORD(wParam);
  1912.             if (lpEntry->nSig == AfxSig_vwwW)
  1913.                 (this->*mmf.pfn_vwwW)(nScrollCode, nPos,
  1914.                     CWnd::FromHandle((HWND)lParam));
  1915.             else
  1916.                 (this->*mmf.pfn_vwwx)(nScrollCode, nPos);
  1917.         }
  1918.         break;
  1919.  
  1920.     case AfxSig_vs:
  1921.         (this->*mmf.pfn_vs)((LPTSTR)lParam);
  1922.         break;
  1923.  
  1924.     case AfxSig_vws:
  1925.         (this->*mmf.pfn_vws)((UINT) wParam, (LPCTSTR)lParam);
  1926.         break;
  1927.  
  1928.     case AfxSig_vOWNER:
  1929.         (this->*mmf.pfn_vOWNER)((int)wParam, (LPTSTR)lParam);
  1930.         lResult = TRUE;
  1931.         break;
  1932.  
  1933.     case AfxSig_iis:
  1934.         lResult = (this->*mmf.pfn_iis)((int)wParam, (LPTSTR)lParam);
  1935.         break;
  1936.  
  1937.     case AfxSig_wp:
  1938.         {
  1939.             CPoint point((DWORD)lParam);
  1940.             lResult = (this->*mmf.pfn_wp)(point);
  1941.         }
  1942.         break;
  1943.  
  1944.     case AfxSig_wv: // AfxSig_bv, AfxSig_wv
  1945.         lResult = (this->*mmf.pfn_wv)();
  1946.         break;
  1947.  
  1948.     case AfxSig_vCALC:
  1949.         (this->*mmf.pfn_vCALC)((BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam);
  1950.         break;
  1951.  
  1952.     case AfxSig_vPOS:
  1953.         (this->*mmf.pfn_vPOS)((WINDOWPOS*)lParam);
  1954.         break;
  1955.  
  1956.     case AfxSig_vwwh:
  1957.         (this->*mmf.pfn_vwwh)(LOWORD(wParam), HIWORD(wParam), (HANDLE)lParam);
  1958.         break;
  1959.  
  1960.     case AfxSig_vwp:
  1961.         {
  1962.             CPoint point((DWORD)lParam);
  1963.             (this->*mmf.pfn_vwp)(wParam, point);
  1964.             break;
  1965.         }
  1966.     case AfxSig_vwSIZING:
  1967.         (this->*mmf.pfn_vwl)(wParam, lParam);
  1968.         lResult = TRUE;
  1969.         break;
  1970.  
  1971.     case AfxSig_bwsp:
  1972.         lResult = (this->*mmf.pfn_bwsp)(LOWORD(wParam), (short) HIWORD(wParam),
  1973.             CPoint(LOWORD(lParam), HIWORD(lParam)));
  1974.         if (!lResult)
  1975.             return FALSE;
  1976.     }
  1977.     goto LReturnTrue;
  1978.  
  1979. LDispatchRegistered:    // for registered windows messages
  1980.     ASSERT(message >= 0xC000);
  1981.     mmf.pfn = lpEntry->pfn;
  1982.     lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
  1983.  
  1984. LReturnTrue:
  1985.     if (pResult != NULL)
  1986.         *pResult = lResult;
  1987.     return TRUE;
  1988. }
  1989.  
  1990. /////////////////////////////////////////////////////////////////////////////
  1991. // CTestCmdUI - used to test for disabled commands before dispatching
  1992.  
  1993. class CTestCmdUI : public CCmdUI
  1994. {
  1995. public:
  1996.     CTestCmdUI();
  1997.  
  1998. public: // re-implementations only
  1999.     virtual void Enable(BOOL bOn);
  2000.     virtual void SetCheck(int nCheck);
  2001.     virtual void SetRadio(BOOL bOn);
  2002.     virtual void SetText(LPCTSTR);
  2003.  
  2004.     BOOL m_bEnabled;
  2005. };
  2006.  
  2007. CTestCmdUI::CTestCmdUI()
  2008. {
  2009.     m_bEnabled = TRUE;  // assume it is enabled
  2010. }
  2011.  
  2012. void CTestCmdUI::Enable(BOOL bOn)
  2013. {
  2014.     m_bEnabled = bOn;
  2015.     m_bEnableChanged = TRUE;
  2016. }
  2017.  
  2018. void CTestCmdUI::SetCheck(int)
  2019. {
  2020.     // do nothing -- just want to know about calls to Enable
  2021. }
  2022.  
  2023. void CTestCmdUI::SetRadio(BOOL)
  2024. {
  2025.     // do nothing -- just want to know about calls to Enable
  2026. }
  2027.  
  2028. void CTestCmdUI::SetText(LPCTSTR)
  2029. {
  2030.     // do nothing -- just want to know about calls to Enable
  2031. }
  2032.  
  2033. /////////////////////////////////////////////////////////////////////////////
  2034. // CWnd command handling
  2035.  
  2036. BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
  2037.     // return TRUE if command invocation was attempted
  2038. {
  2039.     UINT nID = LOWORD(wParam);
  2040.     HWND hWndCtrl = (HWND)lParam;
  2041.     int nCode = HIWORD(wParam);
  2042.  
  2043.     // default routing for command messages (through closure table)
  2044.  
  2045.     if (hWndCtrl == NULL)
  2046.     {
  2047.         // zero IDs for normal commands are not allowed
  2048.         if (nID == 0)
  2049.             return FALSE;
  2050.  
  2051.         // make sure command has not become disabled before routing
  2052.         CTestCmdUI state;
  2053.         state.m_nID = nID;
  2054.         OnCmdMsg(nID, CN_UPDATE_COMMAND_UI, &state, NULL);
  2055.         if (!state.m_bEnabled)
  2056.         {
  2057.             TRACE1("Warning: not executing disabled command %d\n", nID);
  2058.             return TRUE;
  2059.         }
  2060.  
  2061.         // menu or accelerator
  2062.         nCode = CN_COMMAND;
  2063.     }
  2064.     else
  2065.     {
  2066.         // control notification
  2067.         ASSERT(nID == 0 || ::IsWindow(hWndCtrl));
  2068.  
  2069.         if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
  2070.             return TRUE;        // locked out - ignore control notification
  2071.  
  2072.         // reflect notification to child window control
  2073.         if (ReflectLastMsg(hWndCtrl))
  2074.             return TRUE;    // eaten by child
  2075.  
  2076.         // zero IDs for normal commands are not allowed
  2077.         if (nID == 0)
  2078.             return FALSE;
  2079.     }
  2080.  
  2081. #ifdef _DEBUG
  2082.     if (nCode < 0 && nCode != (int)0x8000)
  2083.         TRACE1("Implementation Warning: control notification = $%X.\n",
  2084.             nCode);
  2085. #endif
  2086.  
  2087.     return OnCmdMsg(nID, nCode, NULL, NULL);
  2088. }
  2089.  
  2090. BOOL CWnd::OnNotify(WPARAM, LPARAM lParam, LRESULT* pResult)
  2091. {
  2092.     ASSERT(pResult != NULL);
  2093.     NMHDR* pNMHDR = (NMHDR*)lParam;
  2094.     HWND hWndCtrl = pNMHDR->hwndFrom;
  2095.  
  2096.     // get the child ID from the window itself
  2097.     UINT nID = _AfxGetDlgCtrlID(hWndCtrl);
  2098.     int nCode = pNMHDR->code;
  2099.  
  2100.     ASSERT(hWndCtrl != NULL);
  2101.     ASSERT(::IsWindow(hWndCtrl));
  2102.  
  2103.     if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
  2104.         return TRUE;        // locked out - ignore control notification
  2105.  
  2106.     // reflect notification to child window control
  2107.     if (ReflectLastMsg(hWndCtrl, pResult))
  2108.         return TRUE;        // eaten by child
  2109.  
  2110.     AFX_NOTIFY notify;
  2111.     notify.pResult = pResult;
  2112.     notify.pNMHDR = pNMHDR;
  2113.     return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY), ¬ify, NULL);
  2114. }
  2115.  
  2116. /////////////////////////////////////////////////////////////////////////////
  2117. // CWnd extensions
  2118.  
  2119. CFrameWnd* CWnd::GetParentFrame() const
  2120. {
  2121.     if (GetSafeHwnd() == NULL) // no Window attached
  2122.         return NULL;
  2123.  
  2124.     ASSERT_VALID(this);
  2125.  
  2126.     CWnd* pParentWnd = GetParent();  // start with one parent up
  2127.     while (pParentWnd != NULL)
  2128.     {
  2129.         if (pParentWnd->IsFrameWnd())
  2130.             return (CFrameWnd*)pParentWnd;
  2131.         pParentWnd = pParentWnd->GetParent();
  2132.     }
  2133.     return NULL;
  2134. }
  2135.  
  2136. HWND AFXAPI AfxGetParentOwner(HWND hWnd)
  2137. {
  2138.     // check for permanent-owned window first
  2139.     CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  2140.     if (pWnd != NULL)
  2141.         return pWnd->GetOwner()->GetSafeHwnd();
  2142.  
  2143.     // otherwise, return parent in the Windows sense
  2144.     return (::GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ?
  2145.         ::GetParent(hWnd) : ::GetWindow(hWnd, GW_OWNER);
  2146. }
  2147.  
  2148. CWnd* CWnd::GetTopLevelParent() const
  2149. {
  2150.     if (GetSafeHwnd() == NULL) // no Window attached
  2151.         return NULL;
  2152.  
  2153.     ASSERT_VALID(this);
  2154.  
  2155.     HWND hWndParent = m_hWnd;
  2156.     HWND hWndT;
  2157.     while ((hWndT = AfxGetParentOwner(hWndParent)) != NULL)
  2158.         hWndParent = hWndT;
  2159.  
  2160.     return CWnd::FromHandle(hWndParent);
  2161. }
  2162.  
  2163. CWnd* CWnd::GetTopLevelOwner() const
  2164. {
  2165.     if (GetSafeHwnd() == NULL) // no Window attached
  2166.         return NULL;
  2167.  
  2168.     ASSERT_VALID(this);
  2169.  
  2170.     HWND hWndOwner = m_hWnd;
  2171.     HWND hWndT;
  2172.     while ((hWndT = ::GetWindow(hWndOwner, GW_OWNER)) != NULL)
  2173.         hWndOwner = hWndT;
  2174.  
  2175.     return CWnd::FromHandle(hWndOwner);
  2176. }
  2177.  
  2178. CWnd* CWnd::GetParentOwner() const
  2179. {
  2180.     if (GetSafeHwnd() == NULL) // no Window attached
  2181.         return NULL;
  2182.  
  2183.     ASSERT_VALID(this);
  2184.  
  2185.     HWND hWndParent = m_hWnd;
  2186.     HWND hWndT;
  2187.     while ((::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) &&
  2188.         (hWndT = ::GetParent(hWndParent)) != NULL)
  2189.     {
  2190.         hWndParent = hWndT;
  2191.     }
  2192.  
  2193.     return CWnd::FromHandle(hWndParent);
  2194. }
  2195.  
  2196. BOOL CWnd::IsTopParentActive() const
  2197. {
  2198.     ASSERT(m_hWnd != NULL);
  2199.     ASSERT_VALID(this);
  2200.  
  2201.     return CWnd::GetForegroundWindow() ==
  2202.         GetTopLevelParent()->GetLastActivePopup();
  2203. }
  2204.  
  2205. void CWnd::ActivateTopParent()
  2206. {
  2207.     // special activate logic for floating toolbars and palettes
  2208.     CWnd* pTopLevel = GetTopLevelParent();
  2209.     CWnd* pActiveWnd = GetForegroundWindow();
  2210.     if (pActiveWnd == NULL ||
  2211.         !(pActiveWnd->m_hWnd == m_hWnd || ::IsChild(pActiveWnd->m_hWnd, m_hWnd)))
  2212.     {
  2213.         // clicking on floating frame when it does not have
  2214.         // focus itself -- activate the toplevel frame instead.
  2215.         pTopLevel->SetForegroundWindow();
  2216.     }
  2217. }
  2218.  
  2219. CFrameWnd* CWnd::GetTopLevelFrame() const
  2220. {
  2221.     if (GetSafeHwnd() == NULL) // no Window attached
  2222.         return NULL;
  2223.  
  2224.     ASSERT_VALID(this);
  2225.  
  2226.     CFrameWnd* pFrameWnd = (CFrameWnd*)this;
  2227.     if (!IsFrameWnd())
  2228.         pFrameWnd = GetParentFrame();
  2229.  
  2230.     if (pFrameWnd != NULL)
  2231.     {
  2232.         CFrameWnd* pTemp;
  2233.         while ((pTemp = pFrameWnd->GetParentFrame()) != NULL)
  2234.             pFrameWnd = pTemp;
  2235.     }
  2236.     return pFrameWnd;
  2237. }
  2238.  
  2239. CWnd* PASCAL CWnd::GetSafeOwner(CWnd* pParent, HWND* pWndTop)
  2240. {
  2241.     HWND hWnd = GetSafeOwner_(pParent->GetSafeHwnd(), pWndTop);
  2242.     return CWnd::FromHandle(hWnd);
  2243. }
  2244.  
  2245. int CWnd::MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType)
  2246. {
  2247.     if (lpszCaption == NULL)
  2248.         lpszCaption = AfxGetAppName();
  2249.     int nResult = ::MessageBox(GetSafeHwnd(), lpszText, lpszCaption, nType);
  2250.     return nResult;
  2251. }
  2252.  
  2253. CWnd* PASCAL CWnd::GetDescendantWindow(HWND hWnd, int nID, BOOL bOnlyPerm)
  2254. {
  2255.     // GetDlgItem recursive (return first found)
  2256.     // breadth-first for 1 level, then depth-first for next level
  2257.  
  2258.     // use GetDlgItem since it is a fast USER function
  2259.     HWND hWndChild;
  2260.     CWnd* pWndChild;
  2261.     if ((hWndChild = ::GetDlgItem(hWnd, nID)) != NULL)
  2262.     {
  2263.         if (::GetTopWindow(hWndChild) != NULL)
  2264.         {
  2265.             // children with the same ID as their parent have priority
  2266.             pWndChild = GetDescendantWindow(hWndChild, nID, bOnlyPerm);
  2267.             if (pWndChild != NULL)
  2268.                 return pWndChild;
  2269.         }
  2270.         // return temporary handle if allowed
  2271.         if (!bOnlyPerm)
  2272.             return CWnd::FromHandle(hWndChild);
  2273.  
  2274.         // return only permanent handle
  2275.         pWndChild = CWnd::FromHandlePermanent(hWndChild);
  2276.         if (pWndChild != NULL)
  2277.             return pWndChild;
  2278.     }
  2279.  
  2280.     // walk each child
  2281.     for (hWndChild = ::GetTopWindow(hWnd); hWndChild != NULL;
  2282.         hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  2283.     {
  2284.         pWndChild = GetDescendantWindow(hWndChild, nID, bOnlyPerm);
  2285.         if (pWndChild != NULL)
  2286.             return pWndChild;
  2287.     }
  2288.     return NULL;    // not found
  2289. }
  2290.  
  2291. void PASCAL CWnd::SendMessageToDescendants(HWND hWnd, UINT message,
  2292.     WPARAM wParam, LPARAM lParam, BOOL bDeep, BOOL bOnlyPerm)
  2293. {
  2294.     // walk through HWNDs to avoid creating temporary CWnd objects
  2295.     // unless we need to call this function recursively
  2296.     for (HWND hWndChild = ::GetTopWindow(hWnd); hWndChild != NULL;
  2297.         hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  2298.     {
  2299.         // if bOnlyPerm is TRUE, don't send to non-permanent windows
  2300.         if (bOnlyPerm)
  2301.         {
  2302.             CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
  2303.             if (pWnd != NULL)
  2304.             {
  2305.                 // call window proc directly since it is a C++ window
  2306.                 AfxCallWndProc(pWnd, pWnd->m_hWnd, message, wParam, lParam);
  2307.             }
  2308.         }
  2309.         else
  2310.         {
  2311.             // send message with Windows SendMessage API
  2312.             ::SendMessage(hWndChild, message, wParam, lParam);
  2313.         }
  2314.         if (bDeep && ::GetTopWindow(hWndChild) != NULL)
  2315.         {
  2316.             // send to child windows after parent
  2317.             SendMessageToDescendants(hWndChild, message, wParam, lParam,
  2318.                 bDeep, bOnlyPerm);
  2319.         }
  2320.     }
  2321. }
  2322.  
  2323. /////////////////////////////////////////////////////////////////////////////
  2324. // Scroll bar helpers
  2325. //  hook for CWnd functions
  2326. //    only works for derived class (eg: CView) that override 'GetScrollBarCtrl'
  2327. // if the window doesn't have a _visible_ windows scrollbar - then
  2328. //   look for a sibling with the appropriate ID
  2329.  
  2330. CScrollBar* CWnd::GetScrollBarCtrl(int) const
  2331. {
  2332.     return NULL;        // no special scrollers supported
  2333. }
  2334.  
  2335. int CWnd::SetScrollPos(int nBar, int nPos, BOOL bRedraw)
  2336. {
  2337.     CScrollBar* pScrollBar;
  2338.     if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2339.         return pScrollBar->SetScrollPos(nPos, bRedraw);
  2340.     else
  2341.         return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw);
  2342. }
  2343.  
  2344. int CWnd::GetScrollPos(int nBar) const
  2345. {
  2346.     CScrollBar* pScrollBar;
  2347.     if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2348.         return pScrollBar->GetScrollPos();
  2349.     else
  2350.         return ::GetScrollPos(m_hWnd, nBar);
  2351. }
  2352.  
  2353. void CWnd::SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw)
  2354. {
  2355.     CScrollBar* pScrollBar;
  2356.     if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2357.         pScrollBar->SetScrollRange(nMinPos, nMaxPos, bRedraw);
  2358.     else
  2359.         ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
  2360. }
  2361.  
  2362. void CWnd::GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
  2363. {
  2364.     CScrollBar* pScrollBar;
  2365.     if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2366.         pScrollBar->GetScrollRange(lpMinPos, lpMaxPos);
  2367.     else
  2368.         ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos);
  2369. }
  2370.  
  2371. // Turn on/off non-control scrollbars
  2372. //   for WS_?SCROLL scrollbars - show/hide them
  2373. //   for control scrollbar - enable/disable them
  2374. void CWnd::EnableScrollBarCtrl(int nBar, BOOL bEnable)
  2375. {
  2376.     CScrollBar* pScrollBar;
  2377.     if (nBar == SB_BOTH)
  2378.     {
  2379.         EnableScrollBarCtrl(SB_HORZ, bEnable);
  2380.         EnableScrollBarCtrl(SB_VERT, bEnable);
  2381.     }
  2382.     else if ((pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2383.     {
  2384.         // control scrollbar - enable or disable
  2385.         pScrollBar->EnableWindow(bEnable);
  2386.     }
  2387.     else
  2388.     {
  2389.         // WS_?SCROLL scrollbar - show or hide
  2390.         ShowScrollBar(nBar, bEnable);
  2391.     }
  2392. }
  2393.  
  2394. BOOL CWnd::SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw)
  2395. {
  2396.     ASSERT(lpScrollInfo != NULL);
  2397.     if (afxData.nWinVer < 0x333)
  2398.         return FALSE;
  2399.  
  2400.     HWND hWnd = m_hWnd;
  2401.     CScrollBar* pScrollBar;
  2402.     if (nBar != SB_CTL && (pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2403.     {
  2404.         hWnd = pScrollBar->m_hWnd;
  2405.         nBar = SB_CTL;
  2406.     }
  2407.     lpScrollInfo->cbSize = sizeof(*lpScrollInfo);
  2408.     ::SetScrollInfo(hWnd, nBar, lpScrollInfo, bRedraw);
  2409.     return TRUE;
  2410. }
  2411.  
  2412. BOOL CWnd::GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, UINT nMask)
  2413. {
  2414.     ASSERT(lpScrollInfo != NULL);
  2415.     if (afxData.nWinVer < 0x333)
  2416.         return FALSE;
  2417.  
  2418.     HWND hWnd = m_hWnd;
  2419.     CScrollBar* pScrollBar;
  2420.     if (nBar != SB_CTL && (pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
  2421.     {
  2422.         hWnd = pScrollBar->m_hWnd;
  2423.         nBar = SB_CTL;
  2424.     }
  2425.     lpScrollInfo->cbSize = sizeof(*lpScrollInfo);
  2426.     lpScrollInfo->fMask = nMask;
  2427.     return ::GetScrollInfo(hWnd, nBar, lpScrollInfo);
  2428. }
  2429.  
  2430. int CWnd::GetScrollLimit(int nBar)
  2431. {
  2432.     int nMin, nMax;
  2433.     GetScrollRange(nBar, &nMin, &nMax);
  2434.     SCROLLINFO info;
  2435.     if (GetScrollInfo(nBar, &info, SIF_PAGE))
  2436.     {
  2437.         nMax -= __max(info.nPage-1,0);
  2438.     }
  2439.     return nMax;
  2440. }
  2441.  
  2442. void CWnd::ScrollWindow(int xAmount, int yAmount,
  2443.     LPCRECT lpRect, LPCRECT lpClipRect)
  2444. {
  2445.     ASSERT(::IsWindow(m_hWnd));
  2446.  
  2447.     if (IsWindowVisible() || lpRect != NULL || lpClipRect != NULL)
  2448.     {
  2449.         // When visible, let Windows do the scrolling
  2450.         ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect);
  2451.     }
  2452.     else
  2453.     {
  2454.         // Windows does not perform any scrolling if the window is
  2455.         // not visible.  This leaves child windows unscrolled.
  2456.         // To account for this oversight, the child windows are moved
  2457.         // directly instead.
  2458.         HWND hWndChild = ::GetWindow(m_hWnd, GW_CHILD);
  2459.         if (hWndChild != NULL)
  2460.         {
  2461.             for (; hWndChild != NULL;
  2462.                 hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  2463.             {
  2464.                 CRect rect;
  2465.                 ::GetWindowRect(hWndChild, &rect);
  2466.                 ScreenToClient(&rect);
  2467.                 ::SetWindowPos(hWndChild, NULL,
  2468.                     rect.left+xAmount, rect.top+yAmount, 0, 0,
  2469.                     SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
  2470.             }
  2471.         }
  2472.     }
  2473.  
  2474. #ifndef _AFX_NO_OCC_SUPPORT
  2475.  
  2476.     if ((m_pCtrlCont == NULL) || (lpRect != NULL))
  2477.         return;
  2478.  
  2479.     // the following code is for OLE control containers only
  2480.  
  2481.     m_pCtrlCont->ScrollChildren(xAmount, yAmount);
  2482.  
  2483. #endif // !_AFX_NO_OCC_SUPPORT
  2484. }
  2485.  
  2486. /////////////////////////////////////////////////////////////////////////////
  2487. // minimal layout support
  2488.  
  2489. void CWnd::RepositionBars(UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver,
  2490.     UINT nFlags, LPRECT lpRectParam, LPCRECT lpRectClient, BOOL bStretch)
  2491. {
  2492.     ASSERT(nFlags == 0 || nFlags == reposQuery || nFlags == reposExtra);
  2493.  
  2494.     // walk kids in order, control bars get the resize notification
  2495.     //   which allow them to shrink the client area
  2496.     // remaining size goes to the 'nIDLeftOver' pane
  2497.     // NOTE: nIDFirst->nIDLast are usually 0->0xffff
  2498.  
  2499.     AFX_SIZEPARENTPARAMS layout;
  2500.     HWND hWndLeftOver = NULL;
  2501.  
  2502.     layout.bStretch = bStretch;
  2503.     layout.sizeTotal.cx = layout.sizeTotal.cy = 0;
  2504.     if (lpRectClient != NULL)
  2505.         layout.rect = *lpRectClient;    // starting rect comes from parameter
  2506.     else
  2507.         GetClientRect(&layout.rect);    // starting rect comes from client rect
  2508.  
  2509.     if (nFlags != reposQuery)
  2510.         layout.hDWP = ::BeginDeferWindowPos(8); // reasonable guess
  2511.     else
  2512.         layout.hDWP = NULL; // not actually doing layout
  2513.  
  2514.     for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  2515.         hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  2516.     {
  2517.         UINT nIDC = _AfxGetDlgCtrlID(hWndChild);
  2518.         CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
  2519.         if (nIDC == nIDLeftOver)
  2520.             hWndLeftOver = hWndChild;
  2521.         else if (nIDC >= nIDFirst && nIDC <= nIDLast && pWnd != NULL)
  2522.             ::SendMessage(hWndChild, WM_SIZEPARENT, 0, (LPARAM)&layout);
  2523.     }
  2524.  
  2525.     // if just getting the available rectangle, return it now...
  2526.     if (nFlags == reposQuery)
  2527.     {
  2528.         ASSERT(lpRectParam != NULL);
  2529.         if (bStretch)
  2530.             ::CopyRect(lpRectParam, &layout.rect);
  2531.         else
  2532.         {
  2533.             lpRectParam->left = lpRectParam->top = 0;
  2534.             lpRectParam->right = layout.sizeTotal.cx;
  2535.             lpRectParam->bottom = layout.sizeTotal.cy;
  2536.         }
  2537.         return;
  2538.     }
  2539.  
  2540.     // the rest is the client size of the left-over pane
  2541.     if (nIDLeftOver != 0 && hWndLeftOver != NULL)
  2542.     {
  2543.         CWnd* pLeftOver = CWnd::FromHandle(hWndLeftOver);
  2544.         // allow extra space as specified by lpRectBorder
  2545.         if (nFlags == reposExtra)
  2546.         {
  2547.             ASSERT(lpRectParam != NULL);
  2548.             layout.rect.left += lpRectParam->left;
  2549.             layout.rect.top += lpRectParam->top;
  2550.             layout.rect.right -= lpRectParam->right;
  2551.             layout.rect.bottom -= lpRectParam->bottom;
  2552.         }
  2553.         // reposition the window
  2554.         pLeftOver->CalcWindowRect(&layout.rect);
  2555.         AfxRepositionWindow(&layout, hWndLeftOver, &layout.rect);
  2556.     }
  2557.  
  2558.     // move and resize all the windows at once!
  2559.     if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
  2560.         TRACE0("Warning: DeferWindowPos failed - low system resources.\n");
  2561. }
  2562.  
  2563. void AFXAPI AfxRepositionWindow(AFX_SIZEPARENTPARAMS* lpLayout,
  2564.     HWND hWnd, LPCRECT lpRect)
  2565. {
  2566.     ASSERT(hWnd != NULL);
  2567.     ASSERT(lpRect != NULL);
  2568.     HWND hWndParent = ::GetParent(hWnd);
  2569.     ASSERT(hWndParent != NULL);
  2570.  
  2571.     if (lpLayout != NULL && lpLayout->hDWP == NULL)
  2572.         return;
  2573.  
  2574.     // first check if the new rectangle is the same as the current
  2575.     CRect rectOld;
  2576.     ::GetWindowRect(hWnd, rectOld);
  2577.     ::ScreenToClient(hWndParent, &rectOld.TopLeft());
  2578.     ::ScreenToClient(hWndParent, &rectOld.BottomRight());
  2579.     if (::EqualRect(rectOld, lpRect))
  2580.         return;     // nothing to do
  2581.  
  2582.     // try to use DeferWindowPos for speed, otherwise use SetWindowPos
  2583.     if (lpLayout != NULL)
  2584.     {
  2585.         lpLayout->hDWP = ::DeferWindowPos(lpLayout->hDWP, hWnd, NULL,
  2586.             lpRect->left, lpRect->top,  lpRect->right - lpRect->left,
  2587.             lpRect->bottom - lpRect->top, SWP_NOACTIVATE|SWP_NOZORDER);
  2588.     }
  2589.     else
  2590.     {
  2591.         ::SetWindowPos(hWnd, NULL, lpRect->left, lpRect->top,
  2592.             lpRect->right - lpRect->left, lpRect->bottom - lpRect->top,
  2593.             SWP_NOACTIVATE|SWP_NOZORDER);
  2594.     }
  2595. }
  2596.  
  2597. void CWnd::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
  2598. {
  2599.     DWORD dwExStyle = GetExStyle();
  2600.     if (nAdjustType == 0)
  2601.         dwExStyle &= ~WS_EX_CLIENTEDGE;
  2602.     ::AdjustWindowRectEx(lpClientRect, GetStyle(), FALSE, dwExStyle);
  2603. }
  2604.  
  2605. /////////////////////////////////////////////////////////////////////////////
  2606. // Special keyboard/system command processing
  2607.  
  2608. BOOL CWnd::HandleFloatingSysCommand(UINT nID, LPARAM lParam)
  2609. {
  2610.     CWnd* pParent = GetTopLevelParent();
  2611.     switch (nID & 0xfff0)
  2612.     {
  2613.     case SC_PREVWINDOW:
  2614.     case SC_NEXTWINDOW:
  2615.         if (LOWORD(lParam) == VK_F6 && pParent != NULL)
  2616.         {
  2617.             pParent->SetFocus();
  2618.             return TRUE;
  2619.         }
  2620.         break;
  2621.  
  2622.     case SC_CLOSE:
  2623.     case SC_KEYMENU:
  2624.         // Check lParam.  If it is 0L, then the user may have done
  2625.         // an Alt+Tab, so just ignore it.  This breaks the ability to
  2626.         // just press the Alt-key and have the first menu selected,
  2627.         // but this is minor compared to what happens in the Alt+Tab
  2628.         // case.
  2629.         if ((nID & 0xfff0) == SC_CLOSE || lParam != 0L)
  2630.         {
  2631.             if (pParent != NULL)
  2632.             {
  2633.                 // Sending the above WM_SYSCOMMAND may destroy the app,
  2634.                 // so we have to be careful about restoring activation
  2635.                 // and focus after sending it.
  2636.                 HWND hWndSave = m_hWnd;
  2637.                 HWND hWndFocus = ::GetFocus();
  2638.                 pParent->SetActiveWindow();
  2639.                 pParent->SendMessage(WM_SYSCOMMAND, nID, lParam);
  2640.  
  2641.                 // be very careful here...
  2642.                 if (::IsWindow(hWndSave))
  2643.                     ::SetActiveWindow(hWndSave);
  2644.                 if (::IsWindow(hWndFocus))
  2645.                     ::SetFocus(hWndFocus);
  2646.             }
  2647.         }
  2648.         return TRUE;
  2649.     }
  2650.     return FALSE;
  2651. }
  2652.  
  2653. BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
  2654. {
  2655.     ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
  2656.     ASSERT(pMsg != NULL);
  2657.  
  2658.     // walk from the target window up to the hWndStop window checking
  2659.     //  if any window wants to translate this message
  2660.  
  2661.     for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
  2662.     {
  2663.         CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  2664.         if (pWnd != NULL)
  2665.         {
  2666.             // target window is a C++ window
  2667.             if (pWnd->PreTranslateMessage(pMsg))
  2668.                 return TRUE; // trapped by target window (eg: accelerators)
  2669.         }
  2670.  
  2671.         // got to hWndStop window without interest
  2672.         if (hWnd == hWndStop)
  2673.             break;
  2674.     }
  2675.     return FALSE;       // no special processing
  2676. }
  2677.  
  2678. BOOL CWnd::SendChildNotifyLastMsg(LRESULT* pResult)
  2679. {
  2680.     _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  2681.     return OnChildNotify(pThreadState->m_lastSentMsg.message,
  2682.         pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam, pResult);
  2683. }
  2684.  
  2685. BOOL PASCAL CWnd::ReflectLastMsg(HWND hWndChild, LRESULT* pResult)
  2686. {
  2687.     // get the map, and if no map, then this message does not need reflection
  2688.     CHandleMap* pMap = afxMapHWND();
  2689.     if (pMap == NULL)
  2690.         return FALSE;
  2691.  
  2692.     // check if in permanent map, if it is reflect it (could be OLE control)
  2693.     CWnd* pWnd = (CWnd*)pMap->LookupPermanent(hWndChild);
  2694.     ASSERT(pWnd == NULL || pWnd->m_hWnd == hWndChild);
  2695.     if (pWnd == NULL)
  2696.     {
  2697. #ifndef _AFX_NO_OCC_SUPPORT
  2698.         // check if the window is an OLE control
  2699.         CWnd* pWndParent = (CWnd*)pMap->LookupPermanent(::GetParent(hWndChild));
  2700.         if (pWndParent != NULL && pWndParent->m_pCtrlCont != NULL)
  2701.         {
  2702.             // If a matching control site exists, it's an OLE control
  2703.             COleControlSite* pSite = (COleControlSite*)pWndParent->
  2704.                 m_pCtrlCont->m_siteMap.GetValueAt(hWndChild);
  2705.             if (pSite != NULL)
  2706.             {
  2707.                 CWnd wndTemp(hWndChild);
  2708.                 wndTemp.m_pCtrlSite = pSite;
  2709.                 LRESULT lResult = wndTemp.SendChildNotifyLastMsg(pResult);
  2710.                 wndTemp.m_hWnd = NULL;
  2711.                 return lResult;
  2712.             }
  2713.         }
  2714. #endif //!_AFX_NO_OCC_SUPPORT
  2715.         return FALSE;
  2716.     }
  2717.  
  2718.     // only OLE controls and permanent windows will get reflected msgs
  2719.     ASSERT(pWnd != NULL);
  2720.     return pWnd->SendChildNotifyLastMsg(pResult);
  2721. }
  2722.  
  2723. BOOL CWnd::OnChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  2724. {
  2725. #ifndef _AFX_NO_OCC_SUPPORT
  2726.     if (m_pCtrlSite != NULL)
  2727.     {
  2728.         // first forward raw OCM_ messages to OLE control sources
  2729.         LRESULT lResult = SendMessage(OCM__BASE+uMsg, wParam, lParam);
  2730.         if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC &&
  2731.             (HBRUSH)lResult == NULL)
  2732.         {
  2733.             // for WM_CTLCOLOR msgs, returning NULL implies continue routing
  2734.             return FALSE;
  2735.         }
  2736.         if (pResult != NULL)
  2737.             *pResult = lResult;
  2738.         return TRUE;
  2739.     }
  2740. #endif
  2741.  
  2742.     return ReflectChildNotify(uMsg, wParam, lParam, pResult);
  2743. }
  2744.  
  2745. BOOL CWnd::ReflectChildNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  2746. {
  2747.     // Note: reflected messages are send directly to CWnd::OnWndMsg
  2748.     //  and CWnd::OnCmdMsg for speed and because these messages are not
  2749.     //  routed by normal OnCmdMsg routing (they are only dispatched)
  2750.  
  2751.     switch (uMsg)
  2752.     {
  2753.     // normal messages (just wParam, lParam through OnWndMsg)
  2754.     case WM_HSCROLL:
  2755.     case WM_VSCROLL:
  2756.     case WM_PARENTNOTIFY:
  2757.     case WM_DRAWITEM:
  2758.     case WM_MEASUREITEM:
  2759.     case WM_DELETEITEM:
  2760.     case WM_VKEYTOITEM:
  2761.     case WM_CHARTOITEM:
  2762.     case WM_COMPAREITEM:
  2763.         // reflect the message through the message map as WM_REFLECT_BASE+uMsg
  2764.         return CWnd::OnWndMsg(WM_REFLECT_BASE+uMsg, wParam, lParam, pResult);
  2765.  
  2766.     // special case for WM_COMMAND
  2767.     case WM_COMMAND:
  2768.         {
  2769.             // reflect the message through the message map as OCM_COMMAND
  2770.             int nCode = HIWORD(wParam);
  2771.             if (CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_COMMAND), NULL, NULL))
  2772.             {
  2773.                 if (pResult != NULL)
  2774.                     *pResult = 1;
  2775.                 return TRUE;
  2776.             }
  2777.         }
  2778.         break;
  2779.  
  2780.     // special case for WM_NOTIFY
  2781.     case WM_NOTIFY:
  2782.         {
  2783.             // reflect the message through the message map as OCM_NOTIFY
  2784.             NMHDR* pNMHDR = (NMHDR*)lParam;
  2785.             int nCode = pNMHDR->code;
  2786.             AFX_NOTIFY notify;
  2787.             notify.pResult = pResult;
  2788.             notify.pNMHDR = pNMHDR;
  2789.             return CWnd::OnCmdMsg(0, MAKELONG(nCode, WM_REFLECT_BASE+WM_NOTIFY), ¬ify, NULL);
  2790.         }
  2791.  
  2792.     // other special cases (WM_CTLCOLOR family)
  2793.     default:
  2794.         if (uMsg >= WM_CTLCOLORMSGBOX && uMsg <= WM_CTLCOLORSTATIC)
  2795.         {
  2796.             // fill in special struct for compatiblity with 16-bit WM_CTLCOLOR
  2797.             AFX_CTLCOLOR ctl;
  2798.             ctl.hDC = (HDC)wParam;
  2799.             ctl.nCtlType = uMsg - WM_CTLCOLORMSGBOX;
  2800.             ASSERT(ctl.nCtlType >= CTLCOLOR_MSGBOX);
  2801.             ASSERT(ctl.nCtlType <= CTLCOLOR_STATIC);
  2802.  
  2803.             // reflect the message through the message map as OCM_CTLCOLOR
  2804.             BOOL bResult = CWnd::OnWndMsg(WM_REFLECT_BASE+WM_CTLCOLOR, 0, (LPARAM)&ctl, pResult);
  2805.             if ((HBRUSH)*pResult == NULL)
  2806.                 bResult = FALSE;
  2807.             return bResult;
  2808.         }
  2809.         break;
  2810.     }
  2811.  
  2812.     return FALSE;   // let the parent handle it
  2813. }
  2814.  
  2815. void CWnd::OnParentNotify(UINT message, LPARAM lParam)
  2816. {
  2817.     if ((LOWORD(message) == WM_CREATE || LOWORD(message) == WM_DESTROY))
  2818.     {
  2819.         if (ReflectLastMsg((HWND)lParam))
  2820.             return;     // eat it
  2821.     }
  2822.     // not handled - do default
  2823.     Default();
  2824. }
  2825.  
  2826. LRESULT CWnd::OnActivateTopLevel(WPARAM wParam, LPARAM)
  2827. {
  2828.     if (LOWORD(wParam) == WA_INACTIVE)
  2829.     {
  2830.         _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  2831.         if (!(pThreadState->m_lastInfo.uFlags & TTF_ALWAYSTIP))
  2832.             CancelToolTips(TRUE);
  2833.     }
  2834.  
  2835.     return 0;
  2836. }
  2837.  
  2838. void CWnd::OnSysColorChange()
  2839. {
  2840.     CWinApp* pApp = AfxGetApp();
  2841.     if (pApp != NULL && pApp->m_pMainWnd == this)
  2842.     {
  2843.         // recolor global brushes used by control bars
  2844.         afxData.UpdateSysColors();
  2845.     }
  2846.  
  2847. #ifndef _AFX_NO_CTL3D_SUPPORT
  2848.     if (!afxContextIsDLL)
  2849.     {
  2850.         if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this)
  2851.         {
  2852.             _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  2853.             // allow CTL3D32.DLL to be notified of color change
  2854.             if (pCtl3dState->m_pfnColorChange != NULL)
  2855.                 (*pCtl3dState->m_pfnColorChange)();
  2856.         }
  2857.     }
  2858. #endif
  2859.  
  2860.     // forward this message to all other child windows
  2861.     if (!(GetStyle() & WS_CHILD))
  2862.         SendMessageToDescendants(WM_SYSCOLORCHANGE, 0, 0L, TRUE, TRUE);
  2863.  
  2864.     Default();
  2865. }
  2866.  
  2867. BOOL _afxGotScrollLines;
  2868.  
  2869. void CWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
  2870. {
  2871.     UNUSED_ALWAYS(uFlags);
  2872.     UNUSED_ALWAYS(lpszSection);
  2873.  
  2874. #ifndef _AFX_NO_CTL3D_SUPPORT
  2875.     if (!afxContextIsDLL)
  2876.     {
  2877.         _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  2878.         // allow CTL3D32.DLL to update from WIN.INI settings
  2879.         if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this &&
  2880.             pCtl3dState->m_pfnWinIniChange != NULL)
  2881.         {
  2882.             (*pCtl3dState->m_pfnWinIniChange)();
  2883.         }
  2884.     }
  2885. #endif
  2886.     // force refresh of settings that we cache
  2887.     _afxGotScrollLines = FALSE;
  2888.  
  2889.     CWnd::OnDisplayChange(0, 0);    // to update system metrics, etc.
  2890. }
  2891.  
  2892. void CWnd::OnWinIniChange(LPCTSTR lpszSection)
  2893. {
  2894.     UNUSED_ALWAYS(lpszSection);
  2895.  
  2896.     // this function is provided for backward compatibility only
  2897.     // it is called only in Windows NT 3.51; in Windows 95 and
  2898.     // Windows NT, OnSettingChange is called
  2899.  
  2900. #ifndef _AFX_NO_CTL3D_SUPPORT
  2901.     if (!afxContextIsDLL)
  2902.     {
  2903.         _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  2904.         // allow CTL3D32.DLL to update from WIN.INI settings
  2905.         if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this &&
  2906.             pCtl3dState->m_pfnWinIniChange != NULL)
  2907.         {
  2908.             (*pCtl3dState->m_pfnWinIniChange)();
  2909.         }
  2910.     }
  2911. #endif
  2912.  
  2913.     CWnd::OnDisplayChange(0, 0);    // to update system metrics, etc.
  2914. }
  2915.  
  2916. void CWnd::OnDevModeChange(LPTSTR lpDeviceName)
  2917. {
  2918.     CWinApp* pApp = AfxGetApp();
  2919.     if (pApp != NULL && pApp->m_pMainWnd == this)
  2920.         pApp->DevModeChange(lpDeviceName);
  2921.  
  2922.     // forward this message to all other child windows
  2923.     if (!(GetStyle() & WS_CHILD))
  2924.     {
  2925.         const MSG* pMsg = GetCurrentMessage();
  2926.         SendMessageToDescendants(pMsg->message, pMsg->wParam, pMsg->lParam,
  2927.             TRUE, TRUE);
  2928.     }
  2929. }
  2930.  
  2931. BOOL CWnd::OnHelpInfo(HELPINFO* /*pHelpInfo*/)
  2932. {
  2933.     if (!(GetStyle() & WS_CHILD))
  2934.     {
  2935.         CWnd* pMainWnd = AfxGetMainWnd();
  2936.         if (pMainWnd != NULL &&
  2937.             GetKeyState(VK_SHIFT) >= 0 &&
  2938.             GetKeyState(VK_CONTROL) >= 0 &&
  2939.             GetKeyState(VK_MENU) >= 0)
  2940.         {
  2941.             pMainWnd->SendMessage(WM_COMMAND, ID_HELP);
  2942.             return TRUE;
  2943.         }
  2944.     }
  2945.     return Default();
  2946. }
  2947.  
  2948. LRESULT CWnd::OnDisplayChange(WPARAM, LPARAM)
  2949. {
  2950.     // update metrics if this window is the main window
  2951.     if (AfxGetMainWnd() == this)
  2952.     {
  2953.         // update any system metrics cache
  2954.         afxData.UpdateSysMetrics();
  2955.     }
  2956.  
  2957.     // forward this message to all other child windows
  2958.     if (!(GetStyle() & WS_CHILD))
  2959.     {
  2960.         const MSG* pMsg = GetCurrentMessage();
  2961.         SendMessageToDescendants(pMsg->message, pMsg->wParam, pMsg->lParam,
  2962.             TRUE, TRUE);
  2963.     }
  2964.  
  2965.     return Default();
  2966. }
  2967.  
  2968. LRESULT CWnd::OnDragList(WPARAM, LPARAM lParam)
  2969. {
  2970.     LPDRAGLISTINFO lpInfo = (LPDRAGLISTINFO)lParam;
  2971.     ASSERT(lpInfo != NULL);
  2972.  
  2973.     LRESULT lResult;
  2974.     if (ReflectLastMsg(lpInfo->hWnd, &lResult))
  2975.         return (int)lResult;    // eat it
  2976.  
  2977.     // not handled - do default
  2978.     return (int)Default();
  2979. }
  2980.  
  2981. void CWnd::OnHScroll(UINT, UINT, CScrollBar* pScrollBar)
  2982. {
  2983.     if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
  2984.         return;     // eat it
  2985.  
  2986.     Default();
  2987. }
  2988.  
  2989. void CWnd::OnVScroll(UINT, UINT, CScrollBar* pScrollBar)
  2990. {
  2991.     if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
  2992.         return;     // eat it
  2993.  
  2994.     Default();
  2995. }
  2996.  
  2997. void CWnd::OnEnterIdle(UINT /*nWhy*/, CWnd* /*pWho*/)
  2998. {
  2999.     // WINBUG: In some OLE inplace active scenarios, OLE will post a
  3000.     // message instead of sending it.  This causes so many WM_ENTERIDLE
  3001.     // messages to be sent that tasks running in the background stop
  3002.     // running.  By dispatching the pending WM_ENTERIDLE messages
  3003.     // when the first one is received, we trick Windows into thinking
  3004.     // that only one was really sent and dispatched.
  3005.     {
  3006.         MSG msg;
  3007.         while (PeekMessage(&msg, NULL, WM_ENTERIDLE, WM_ENTERIDLE, PM_REMOVE))
  3008.             DispatchMessage(&msg);
  3009.     }
  3010.  
  3011.     Default();
  3012. }
  3013.  
  3014. HBRUSH CWnd::OnCtlColor(CDC*, CWnd* pWnd, UINT)
  3015. {
  3016.     ASSERT(pWnd != NULL && pWnd->m_hWnd != NULL);
  3017.     LRESULT lResult;
  3018.     if (pWnd->SendChildNotifyLastMsg(&lResult))
  3019.         return (HBRUSH)lResult;     // eat it
  3020.     return (HBRUSH)Default();
  3021. }
  3022.  
  3023. #ifndef _AFX_NO_GRAYDLG_SUPPORT
  3024. // special helper for Gray OnCtlColor routines
  3025. HBRUSH CWnd::OnGrayCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
  3026. {
  3027.     LRESULT lResult;
  3028.     if (pWnd->SendChildNotifyLastMsg(&lResult))
  3029.         return (HBRUSH)lResult;     // eat it
  3030.  
  3031.     _AFX_WIN_STATE* pWinState = _afxWinState;
  3032.     if (!GrayCtlColor(pDC->m_hDC, pWnd->GetSafeHwnd(), nCtlColor,
  3033.       pWinState->m_hDlgBkBrush, pWinState->m_crDlgTextClr))
  3034.         return (HBRUSH)Default();
  3035.     return pWinState->m_hDlgBkBrush;
  3036. }
  3037. #endif //!_AFX_NO_GRAYDLG_SUPPORT
  3038.  
  3039. // implementation of OnCtlColor for default gray backgrounds
  3040. //   (works for any window containing controls)
  3041. //  return value of FALSE means caller must call DefWindowProc's default
  3042. //  TRUE means that 'hbrGray' will be used and the appropriate text
  3043. //    ('clrText') and background colors are set.
  3044. BOOL PASCAL CWnd::GrayCtlColor(HDC hDC, HWND hWnd, UINT nCtlColor,
  3045.     HBRUSH hbrGray, COLORREF clrText)
  3046. {
  3047.     if (hDC == NULL)
  3048.     {
  3049.         // sometimes Win32 passes a NULL hDC in the WM_CTLCOLOR message.
  3050.         TRACE0("Warning: hDC is NULL in CWnd::GrayCtlColor; WM_CTLCOLOR not processed.\n");
  3051.         return FALSE;
  3052.     }
  3053.  
  3054.     if (hbrGray == NULL ||
  3055.         nCtlColor == CTLCOLOR_EDIT || nCtlColor == CTLCOLOR_MSGBOX ||
  3056.         nCtlColor == CTLCOLOR_SCROLLBAR)
  3057.     {
  3058.         return FALSE;
  3059.     }
  3060.  
  3061.     if (nCtlColor == CTLCOLOR_LISTBOX)
  3062.     {
  3063.         // only handle requests to draw the space between edit and drop button
  3064.         //  in a drop-down combo (not a drop-down list)
  3065.         if (!_AfxIsComboBoxControl(hWnd, (UINT)CBS_DROPDOWN))
  3066.             return FALSE;
  3067.     }
  3068.  
  3069.     // set background color and return handle to brush
  3070.     LOGBRUSH logbrush;
  3071.     VERIFY(::GetObject(hbrGray, sizeof(LOGBRUSH), (LPVOID)&logbrush));
  3072.     ::SetBkColor(hDC, logbrush.lbColor);
  3073.     if (clrText == (COLORREF)-1)
  3074.         clrText = ::GetSysColor(COLOR_WINDOWTEXT);  // normal text
  3075.     ::SetTextColor(hDC, clrText);
  3076.     return TRUE;
  3077. }
  3078.  
  3079. #ifndef _AFX_NO_CTL3D_SUPPORT
  3080. LRESULT CWnd::OnQuery3dControls(WPARAM, LPARAM)
  3081. {
  3082.     // This is message handler is not in CWnd's message map.
  3083.     // It is placed in various derived classes' message maps to enable
  3084.     // 3D controls for specific window types only.
  3085.  
  3086.     return 0xFFFF;  // CTL3D_ALL
  3087. }
  3088. #endif
  3089.  
  3090. /////////////////////////////////////////////////////////////////////////////
  3091. // 'dialog data' support
  3092.  
  3093. BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
  3094. {
  3095.     ASSERT(::IsWindow(m_hWnd)); // calling UpdateData before DoModal?
  3096.  
  3097.     CDataExchange dx(this, bSaveAndValidate);
  3098.  
  3099.     // prevent control notifications from being dispatched during UpdateData
  3100.     _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  3101.     HWND hWndOldLockout = pThreadState->m_hLockoutNotifyWindow;
  3102.     ASSERT(hWndOldLockout != m_hWnd);   // must not recurse
  3103.     pThreadState->m_hLockoutNotifyWindow = m_hWnd;
  3104.  
  3105.     BOOL bOK = FALSE;       // assume failure
  3106.     TRY
  3107.     {
  3108.         DoDataExchange(&dx);
  3109.         bOK = TRUE;         // it worked
  3110.     }
  3111.     CATCH(CUserException, e)
  3112.     {
  3113.         // validation failed - user already alerted, fall through
  3114.         ASSERT(!bOK);
  3115.         // Note: DELETE_EXCEPTION_(e) not required
  3116.     }
  3117.     AND_CATCH_ALL(e)
  3118.     {
  3119.         // validation failed due to OOM or other resource failure
  3120.         e->ReportError(MB_ICONEXCLAMATION, AFX_IDP_INTERNAL_FAILURE);
  3121.         ASSERT(!bOK);
  3122.         DELETE_EXCEPTION(e);
  3123.     }
  3124.     END_CATCH_ALL
  3125.  
  3126.     pThreadState->m_hLockoutNotifyWindow = hWndOldLockout;
  3127.     return bOK;
  3128. }
  3129.  
  3130. CDataExchange::CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate)
  3131. {
  3132.     ASSERT_VALID(pDlgWnd);
  3133.     m_bSaveAndValidate = bSaveAndValidate;
  3134.     m_pDlgWnd = pDlgWnd;
  3135.     m_hWndLastControl = NULL;
  3136. }
  3137.  
  3138. /////////////////////////////////////////////////////////////////////////////
  3139. // Centering dialog support (works for any non-child window)
  3140.  
  3141. void CWnd::CenterWindow(CWnd* pAlternateOwner)
  3142. {
  3143.     ASSERT(::IsWindow(m_hWnd));
  3144.  
  3145.     // determine owner window to center against
  3146.     DWORD dwStyle = GetStyle();
  3147.     HWND hWndCenter = pAlternateOwner->GetSafeHwnd();
  3148.     if (pAlternateOwner == NULL)
  3149.     {
  3150.         if (dwStyle & WS_CHILD)
  3151.             hWndCenter = ::GetParent(m_hWnd);
  3152.         else
  3153.             hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
  3154.         if (hWndCenter != NULL)
  3155.         {
  3156.             // let parent determine alternate center window
  3157.             HWND hWndTemp =
  3158.                 (HWND)::SendMessage(hWndCenter, WM_QUERYCENTERWND, 0, 0);
  3159.             if (hWndTemp != NULL)
  3160.                 hWndCenter = hWndTemp;
  3161.         }
  3162.     }
  3163.  
  3164.     // get coordinates of the window relative to its parent
  3165.     CRect rcDlg;
  3166.     GetWindowRect(&rcDlg);
  3167.     CRect rcArea;
  3168.     CRect rcCenter;
  3169.     HWND hWndParent;
  3170.     if (!(dwStyle & WS_CHILD))
  3171.     {
  3172.         // don't center against invisible or minimized windows
  3173.         if (hWndCenter != NULL)
  3174.         {
  3175.             DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
  3176.             if (!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
  3177.                 hWndCenter = NULL;
  3178.         }
  3179.  
  3180.         MONITORINFO mi;
  3181.         mi.cbSize = sizeof(mi);
  3182.  
  3183.         // center within appropriate monitor coordinates
  3184.         if (hWndCenter == NULL)
  3185.         {
  3186.             HWND hwDefault = AfxGetMainWnd()->GetSafeHwnd();
  3187.  
  3188.             GetMonitorInfo(
  3189.                 MonitorFromWindow(hwDefault, MONITOR_DEFAULTTOPRIMARY), &mi);
  3190.             rcCenter = mi.rcWork;
  3191.             rcArea = mi.rcWork;
  3192.         }
  3193.         else
  3194.         {
  3195.             ::GetWindowRect(hWndCenter, &rcCenter);
  3196.             GetMonitorInfo(
  3197.                 MonitorFromWindow(hWndCenter, MONITOR_DEFAULTTONEAREST), &mi);
  3198.             rcArea = mi.rcWork;
  3199.         }
  3200.     }
  3201.     else
  3202.     {
  3203.         // center within parent client coordinates
  3204.         hWndParent = ::GetParent(m_hWnd);
  3205.         ASSERT(::IsWindow(hWndParent));
  3206.  
  3207.         ::GetClientRect(hWndParent, &rcArea);
  3208.         ASSERT(::IsWindow(hWndCenter));
  3209.         ::GetClientRect(hWndCenter, &rcCenter);
  3210.         ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
  3211.     }
  3212.  
  3213.     // find dialog's upper left based on rcCenter
  3214.     int xLeft = (rcCenter.left + rcCenter.right) / 2 - rcDlg.Width() / 2;
  3215.     int yTop = (rcCenter.top + rcCenter.bottom) / 2 - rcDlg.Height() / 2;
  3216.  
  3217.     // if the dialog is outside the screen, move it inside
  3218.     if (xLeft < rcArea.left)
  3219.         xLeft = rcArea.left;
  3220.     else if (xLeft + rcDlg.Width() > rcArea.right)
  3221.         xLeft = rcArea.right - rcDlg.Width();
  3222.  
  3223.     if (yTop < rcArea.top)
  3224.         yTop = rcArea.top;
  3225.     else if (yTop + rcDlg.Height() > rcArea.bottom)
  3226.         yTop = rcArea.bottom - rcDlg.Height();
  3227.  
  3228.     // map screen coordinates to child coordinates
  3229.     SetWindowPos(NULL, xLeft, yTop, -1, -1,
  3230.         SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  3231. }
  3232.  
  3233. BOOL CWnd::CheckAutoCenter()
  3234. {
  3235.     return TRUE;
  3236. }
  3237.  
  3238. /////////////////////////////////////////////////////////////////////////////
  3239. // Dialog initialization support
  3240.  
  3241. BOOL CWnd::ExecuteDlgInit(LPCTSTR lpszResourceName)
  3242. {
  3243.     // find resource handle
  3244.     LPVOID lpResource = NULL;
  3245.     HGLOBAL hResource = NULL;
  3246.     if (lpszResourceName != NULL)
  3247.     {
  3248.         HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_DLGINIT);
  3249.         HRSRC hDlgInit = ::FindResource(hInst, lpszResourceName, RT_DLGINIT);
  3250.         if (hDlgInit != NULL)
  3251.         {
  3252.             // load it
  3253.             hResource = LoadResource(hInst, hDlgInit);
  3254.             if (hResource == NULL)
  3255.                 return FALSE;
  3256.             // lock it
  3257.             lpResource = LockResource(hResource);
  3258.             ASSERT(lpResource != NULL);
  3259.         }
  3260.     }
  3261.  
  3262.     // execute it
  3263.     BOOL bResult = ExecuteDlgInit(lpResource);
  3264.  
  3265.     // cleanup
  3266.     if (lpResource != NULL && hResource != NULL)
  3267.     {
  3268.         UnlockResource(hResource);
  3269.         FreeResource(hResource);
  3270.     }
  3271.     return bResult;
  3272. }
  3273.  
  3274. BOOL CWnd::ExecuteDlgInit(LPVOID lpResource)
  3275. {
  3276.     BOOL bSuccess = TRUE;
  3277.     if (lpResource != NULL)
  3278.     {
  3279.         UNALIGNED WORD* lpnRes = (WORD*)lpResource;
  3280.         while (bSuccess && *lpnRes != 0)
  3281.         {
  3282.             WORD nIDC = *lpnRes++;
  3283.             WORD nMsg = *lpnRes++;
  3284.             DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++;
  3285.  
  3286.             // In Win32 the WM_ messages have changed.  They have
  3287.             // to be translated from the 32-bit values to 16-bit
  3288.             // values here.
  3289.  
  3290.             #define WIN16_LB_ADDSTRING  0x0401
  3291.             #define WIN16_CB_ADDSTRING  0x0403
  3292.             #define AFX_CB_ADDSTRING    0x1234
  3293.  
  3294.             // unfortunately, WIN16_CB_ADDSTRING == CBEM_INSERTITEM
  3295.             if (nMsg == AFX_CB_ADDSTRING)
  3296.                 nMsg = CBEM_INSERTITEM;
  3297.             else if (nMsg == WIN16_LB_ADDSTRING)
  3298.                 nMsg = LB_ADDSTRING;
  3299.             else if (nMsg == WIN16_CB_ADDSTRING)
  3300.                 nMsg = CB_ADDSTRING;
  3301.  
  3302.             // check for invalid/unknown message types
  3303. #ifdef _AFX_NO_OCC_SUPPORT
  3304.             ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
  3305.                 nMsg == CBEM_INSERTITEM);
  3306. #else
  3307.             ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
  3308.                 nMsg == CBEM_INSERTITEM ||
  3309.                 nMsg == WM_OCC_LOADFROMSTREAM ||
  3310.                 nMsg == WM_OCC_LOADFROMSTREAM_EX ||
  3311.                 nMsg == WM_OCC_LOADFROMSTORAGE ||
  3312.                 nMsg == WM_OCC_LOADFROMSTORAGE_EX ||
  3313.                 nMsg == WM_OCC_INITNEW);
  3314. #endif
  3315.  
  3316. #ifdef _DEBUG
  3317.             // For AddStrings, the count must exactly delimit the
  3318.             // string, including the NULL termination.  This check
  3319.             // will not catch all mal-formed ADDSTRINGs, but will
  3320.             // catch some.
  3321.             if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING || nMsg == CBEM_INSERTITEM)
  3322.                 ASSERT(*((LPBYTE)lpnRes + (UINT)dwLen - 1) == 0);
  3323. #endif
  3324.  
  3325.             if (nMsg == CBEM_INSERTITEM)
  3326.             {
  3327.                 USES_CONVERSION;
  3328.                 COMBOBOXEXITEM item;
  3329.                 item.mask = CBEIF_TEXT;
  3330.                 item.iItem = -1;
  3331.                 item.pszText = A2T(LPSTR(lpnRes));
  3332.  
  3333.                 if (::SendDlgItemMessage(m_hWnd, nIDC, nMsg, 0, (LPARAM) &item) == -1)
  3334.                     bSuccess = FALSE;
  3335.             }
  3336. #ifndef _AFX_NO_OCC_SUPPORT
  3337.             else if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING)
  3338. #endif // !_AFX_NO_OCC_SUPPORT
  3339.             {
  3340.                 // List/Combobox returns -1 for error
  3341.                 if (::SendDlgItemMessageA(m_hWnd, nIDC, nMsg, 0, (LPARAM) lpnRes) == -1)
  3342.                     bSuccess = FALSE;
  3343.             }
  3344.  
  3345.  
  3346.             // skip past data
  3347.             lpnRes = (WORD*)((LPBYTE)lpnRes + (UINT)dwLen);
  3348.         }
  3349.     }
  3350.  
  3351.     // send update message to all controls after all other siblings loaded
  3352.     if (bSuccess)
  3353.         SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, FALSE, FALSE);
  3354.  
  3355.     return bSuccess;
  3356. }
  3357.  
  3358. void CWnd::UpdateDialogControls(CCmdTarget* pTarget, BOOL bDisableIfNoHndler)
  3359. {
  3360.     CCmdUI state;
  3361.     CWnd wndTemp;       // very temporary window just for CmdUI update
  3362.  
  3363.     // walk all the kids - assume the IDs are for buttons
  3364.     for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  3365.             hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  3366.     {
  3367.         // send to buttons
  3368.         wndTemp.m_hWnd = hWndChild; // quick and dirty attach
  3369.         state.m_nID = _AfxGetDlgCtrlID(hWndChild);
  3370.         state.m_pOther = &wndTemp;
  3371.  
  3372.         // check for reflect handlers in the child window
  3373.         CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
  3374.         if (pWnd != NULL)
  3375.         {
  3376.             // call it directly to disable any routing
  3377.             if (pWnd->CWnd::OnCmdMsg(0, MAKELONG(-1,
  3378.                 WM_COMMAND+WM_REFLECT_BASE), &state, NULL))
  3379.                 continue;
  3380.         }
  3381.  
  3382.         // check for handlers in the parent window
  3383.         if (CWnd::OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL))
  3384.             continue;
  3385.  
  3386.         // determine whether to disable when no handler exists
  3387.         BOOL bDisableTemp = bDisableIfNoHndler;
  3388.         if (bDisableTemp)
  3389.         {
  3390.             if ((wndTemp.SendMessage(WM_GETDLGCODE) & DLGC_BUTTON) == 0)
  3391.             {
  3392.                 // non-button controls don't get automagically disabled
  3393.                 bDisableTemp = FALSE;
  3394.             }
  3395.             else
  3396.             {
  3397.                 // only certain button controls get automagically disabled
  3398.                 UINT nStyle = (UINT)(wndTemp.GetStyle() & 0x0F);
  3399.                 if (nStyle == (UINT)BS_AUTOCHECKBOX ||
  3400.                     nStyle == (UINT)BS_AUTO3STATE ||
  3401.                     nStyle == (UINT)BS_GROUPBOX ||
  3402.                     nStyle == (UINT)BS_AUTORADIOBUTTON)
  3403.                 {
  3404.                     bDisableTemp = FALSE;
  3405.                 }
  3406.             }
  3407.         }
  3408.         // check for handlers in the target (owner)
  3409.         state.DoUpdate(pTarget, bDisableTemp);
  3410.     }
  3411.     wndTemp.m_hWnd = NULL;      // quick and dirty detach
  3412. }
  3413.  
  3414. BOOL CWnd::PreTranslateInput(LPMSG lpMsg)
  3415. {
  3416.     ASSERT(::IsWindow(m_hWnd));
  3417.  
  3418.     // don't translate non-input events
  3419.     if ((lpMsg->message < WM_KEYFIRST || lpMsg->message > WM_KEYLAST) &&
  3420.         (lpMsg->message < WM_MOUSEFIRST || lpMsg->message > WM_MOUSELAST))
  3421.         return FALSE;
  3422.  
  3423.     return IsDialogMessage(lpMsg);
  3424. }
  3425.  
  3426. int CWnd::RunModalLoop(DWORD dwFlags)
  3427. {
  3428.     ASSERT(::IsWindow(m_hWnd)); // window must be created
  3429.     ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state
  3430.  
  3431.     // for tracking the idle time state
  3432.     BOOL bIdle = TRUE;
  3433.     LONG lIdleCount = 0;
  3434.     BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
  3435.     HWND hWndParent = ::GetParent(m_hWnd);
  3436.     m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
  3437.     MSG* pMsg = &AfxGetThread()->m_msgCur;
  3438.  
  3439.     // acquire and dispatch messages until the modal state is done
  3440.     for (;;)
  3441.     {
  3442.         ASSERT(ContinueModal());
  3443.  
  3444.         // phase1: check to see if we can do idle work
  3445.         while (bIdle &&
  3446.             !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
  3447.         {
  3448.             ASSERT(ContinueModal());
  3449.  
  3450.             // show the dialog when the message queue goes idle
  3451.             if (bShowIdle)
  3452.             {
  3453.                 ShowWindow(SW_SHOWNORMAL);
  3454.                 UpdateWindow();
  3455.                 bShowIdle = FALSE;
  3456.             }
  3457.  
  3458.             // call OnIdle while in bIdle state
  3459.             if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
  3460.             {
  3461.                 // send WM_ENTERIDLE to the parent
  3462.                 ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
  3463.             }
  3464.             if ((dwFlags & MLF_NOKICKIDLE) ||
  3465.                 !SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
  3466.             {
  3467.                 // stop idle processing next time
  3468.                 bIdle = FALSE;
  3469.             }
  3470.         }
  3471.  
  3472.         // phase2: pump messages while available
  3473.         do
  3474.         {
  3475.             ASSERT(ContinueModal());
  3476.  
  3477.             // pump message, but quit on WM_QUIT
  3478.             if (!AfxGetThread()->PumpMessage())
  3479.             {
  3480.                 AfxPostQuitMessage(0);
  3481.                 return -1;
  3482.             }
  3483.  
  3484.             // show the window when certain special messages rec'd
  3485.             if (bShowIdle &&
  3486.                 (pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
  3487.             {
  3488.                 ShowWindow(SW_SHOWNORMAL);
  3489.                 UpdateWindow();
  3490.                 bShowIdle = FALSE;
  3491.             }
  3492.  
  3493.             if (!ContinueModal())
  3494.                 goto ExitModal;
  3495.  
  3496.             // reset "no idle" state after pumping "normal" message
  3497.             if (AfxGetThread()->IsIdleMessage(pMsg))
  3498.             {
  3499.                 bIdle = TRUE;
  3500.                 lIdleCount = 0;
  3501.             }
  3502.  
  3503.         } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
  3504.     }
  3505.  
  3506. ExitModal:
  3507.     m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
  3508.     return m_nModalResult;
  3509. }
  3510.  
  3511. BOOL CWnd::ContinueModal()
  3512. {
  3513.     return m_nFlags & WF_CONTINUEMODAL;
  3514. }
  3515.  
  3516. void CWnd::EndModalLoop(int nResult)
  3517. {
  3518.     ASSERT(::IsWindow(m_hWnd));
  3519.  
  3520.     // this result will be returned from CWnd::RunModalLoop
  3521.     m_nModalResult = nResult;
  3522.  
  3523.     // make sure a message goes through to exit the modal loop
  3524.     if (m_nFlags & WF_CONTINUEMODAL)
  3525.     {
  3526.         m_nFlags &= ~WF_CONTINUEMODAL;
  3527.         PostMessage(WM_NULL);
  3528.     }
  3529. }
  3530.  
  3531. #ifndef _AFX_NO_OCC_SUPPORT
  3532.  
  3533. BOOL CWnd::SetOccDialogInfo(_AFX_OCC_DIALOG_INFO*)
  3534. {
  3535.     ASSERT(FALSE); // this class doesn't support dialog creation
  3536.     return FALSE;
  3537. }
  3538.  
  3539. #endif
  3540.  
  3541. /////////////////////////////////////////////////////////////////////////////
  3542. // Standard init called by WinMain
  3543.  
  3544. AFX_STATIC BOOL AFXAPI _AfxRegisterWithIcon(WNDCLASS* pWndCls,
  3545.     LPCTSTR lpszClassName, UINT nIDIcon)
  3546. {
  3547.     pWndCls->lpszClassName = lpszClassName;
  3548.     HINSTANCE hInst = AfxFindResourceHandle(
  3549.         MAKEINTRESOURCE(nIDIcon), RT_GROUP_ICON);
  3550.     if ((pWndCls->hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDIcon))) == NULL)
  3551.     {
  3552.         // use default icon
  3553.         pWndCls->hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
  3554.     }
  3555.     return AfxRegisterClass(pWndCls);
  3556. }
  3557.  
  3558. LONG AFXAPI _AfxInitCommonControls(LPINITCOMMONCONTROLSEX lpInitCtrls, LONG fToRegister)
  3559. {
  3560.     ASSERT(fToRegister != 0);
  3561.  
  3562. #ifndef _AFXDLL
  3563.     HINSTANCE hInstBefore = ::GetModuleHandleA("COMCTL32.DLL");
  3564. #endif
  3565.  
  3566.     // load the COMCTL32.DLL library because it may not be loaded yet (delayload)
  3567.     HINSTANCE hInst = ::LoadLibraryA("COMCTL32.DLL");
  3568.     if (hInst == NULL)
  3569.         return 0;
  3570.  
  3571.     LONG lResult = 0;
  3572.     // attempt to get/call InitCommonControlsEx
  3573.     BOOL (STDAPICALLTYPE* pfnInit)(LPINITCOMMONCONTROLSEX lpInitCtrls) = NULL;
  3574.     (FARPROC&)pfnInit = ::GetProcAddress(hInst, "InitCommonControlsEx");
  3575.     if (pfnInit == NULL)
  3576.     {
  3577.         // not there, so call InitCommonControls if possible
  3578.         if ((fToRegister & AFX_WIN95CTLS_MASK) == fToRegister)
  3579.         {
  3580.             InitCommonControls();
  3581.             lResult = AFX_WIN95CTLS_MASK;
  3582.         }
  3583.     }
  3584. #ifdef _AFXDLL
  3585.     else if (InitCommonControlsEx(lpInitCtrls))
  3586. #else
  3587.     else if ((*pfnInit)(lpInitCtrls))
  3588. #endif
  3589.     {
  3590.         // InitCommonControlsEx was successful so return the full mask
  3591.         lResult = fToRegister;
  3592. #ifndef _AFXDLL
  3593.         if (hInstBefore == NULL)
  3594.         {
  3595.             // In the case that we are statically linked and COMCTL32.DLL
  3596.             // was not loaded before we loaded it with LoadLibrary in this
  3597.             // function, that indicates that the calling module is linked
  3598.             // with /delayload:comctl32.dll, and in this case we have to do
  3599.             // something to cause COMCTL32.DLL to stay loaded.  The only thing
  3600.             // we can do is to call a COMCTL32.DLL API which will cause the
  3601.             // CRT's delay load helpers to get called and will cause the DLL
  3602.             // to get loaded.  We choose to call InitCommonControls because
  3603.             // it exists in the original COMCTL32.DLL and it doesn't really
  3604.             // do any harm to call it, except for the time it takes to
  3605.             // register the set of original Windows 95 classes.
  3606.             // If this isn't done our FreeLibrary call below will cause
  3607.             // COMCTL32.DLL to go away, undoing the registration.
  3608.             InitCommonControls();
  3609.             lResult |= AFX_WIN95CTLS_MASK;
  3610.         }
  3611. #endif
  3612.     }
  3613.  
  3614.     // free the library reference and return the result
  3615.     FreeLibrary(hInst);
  3616.     return lResult;
  3617. }
  3618.  
  3619. BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
  3620. {
  3621.     // mask off all classes that are already registered
  3622.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  3623.     fToRegister &= ~pModuleState->m_fRegisteredClasses;
  3624.     if (fToRegister == 0)
  3625.         return TRUE;
  3626.  
  3627.     LONG fRegisteredClasses = 0;
  3628.  
  3629.     // common initialization
  3630.     WNDCLASS wndcls;
  3631.     memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults
  3632.     wndcls.lpfnWndProc = DefWindowProc;
  3633.     wndcls.hInstance = AfxGetInstanceHandle();
  3634.     wndcls.hCursor = afxData.hcurArrow;
  3635.  
  3636.     INITCOMMONCONTROLSEX init;
  3637.     init.dwSize = sizeof(init);
  3638.  
  3639.     // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go
  3640.     if (fToRegister & AFX_WND_REG)
  3641.     {
  3642.         // Child windows - no brush, no icon, safest default class styles
  3643.         wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  3644.         wndcls.lpszClassName = _afxWnd;
  3645.         if (AfxRegisterClass(&wndcls))
  3646.             fRegisteredClasses |= AFX_WND_REG;
  3647.     }
  3648.     if (fToRegister & AFX_WNDOLECONTROL_REG)
  3649.     {
  3650.         // OLE Control windows - use parent DC for speed
  3651.         wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  3652.         wndcls.lpszClassName = _afxWndOleControl;
  3653.         if (AfxRegisterClass(&wndcls))
  3654.             fRegisteredClasses |= AFX_WNDOLECONTROL_REG;
  3655.     }
  3656.     if (fToRegister & AFX_WNDCONTROLBAR_REG)
  3657.     {
  3658.         // Control bar windows
  3659.         wndcls.style = 0;   // control bars don't handle double click
  3660.         wndcls.lpszClassName = _afxWndControlBar;
  3661.         wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  3662.         if (AfxRegisterClass(&wndcls))
  3663.             fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;
  3664.     }
  3665.     if (fToRegister & AFX_WNDMDIFRAME_REG)
  3666.     {
  3667.         // MDI Frame window (also used for splitter window)
  3668.         wndcls.style = CS_DBLCLKS;
  3669.         wndcls.hbrBackground = NULL;
  3670.         if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))
  3671.             fRegisteredClasses |= AFX_WNDMDIFRAME_REG;
  3672.     }
  3673.     if (fToRegister & AFX_WNDFRAMEORVIEW_REG)
  3674.     {
  3675.         // SDI Frame or MDI Child windows or views - normal colors
  3676.         wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  3677.         wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  3678.         if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
  3679.             fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
  3680.     }
  3681.     if (fToRegister & AFX_WNDCOMMCTLS_REG)
  3682.     {
  3683.         // this flag is compatible with the old InitCommonControls() API
  3684.         init.dwICC = ICC_WIN95_CLASSES;
  3685.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);
  3686.         fToRegister &= ~AFX_WIN95CTLS_MASK;
  3687.     }
  3688.     if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)
  3689.     {
  3690.         init.dwICC = ICC_UPDOWN_CLASS;
  3691.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);
  3692.     }
  3693.     if (fToRegister & AFX_WNDCOMMCTL_TREEVIEW_REG)
  3694.     {
  3695.         init.dwICC = ICC_TREEVIEW_CLASSES;
  3696.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TREEVIEW_REG);
  3697.     }
  3698.     if (fToRegister & AFX_WNDCOMMCTL_TAB_REG)
  3699.     {
  3700.         init.dwICC = ICC_TAB_CLASSES;
  3701.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TAB_REG);
  3702.     }
  3703.     if (fToRegister & AFX_WNDCOMMCTL_PROGRESS_REG)
  3704.     {
  3705.         init.dwICC = ICC_PROGRESS_CLASS;
  3706.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_PROGRESS_REG);
  3707.     }
  3708.     if (fToRegister & AFX_WNDCOMMCTL_LISTVIEW_REG)
  3709.     {
  3710.         init.dwICC = ICC_LISTVIEW_CLASSES;
  3711.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_LISTVIEW_REG);
  3712.     }
  3713.     if (fToRegister & AFX_WNDCOMMCTL_HOTKEY_REG)
  3714.     {
  3715.         init.dwICC = ICC_HOTKEY_CLASS;
  3716.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_HOTKEY_REG);
  3717.     }
  3718.     if (fToRegister & AFX_WNDCOMMCTL_BAR_REG)
  3719.     {
  3720.         init.dwICC = ICC_BAR_CLASSES;
  3721.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_BAR_REG);
  3722.     }
  3723.     if (fToRegister & AFX_WNDCOMMCTL_ANIMATE_REG)
  3724.     {
  3725.         init.dwICC = ICC_ANIMATE_CLASS;
  3726.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ANIMATE_REG);
  3727.     }
  3728.     if (fToRegister & AFX_WNDCOMMCTL_INTERNET_REG)
  3729.     {
  3730.         init.dwICC = ICC_INTERNET_CLASSES;
  3731.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_INTERNET_REG);
  3732.     }
  3733.     if (fToRegister & AFX_WNDCOMMCTL_COOL_REG)
  3734.     {
  3735.         init.dwICC = ICC_COOL_CLASSES;
  3736.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_COOL_REG);
  3737.     }
  3738.     if (fToRegister & AFX_WNDCOMMCTL_USEREX_REG)
  3739.     {
  3740.         init.dwICC = ICC_USEREX_CLASSES;
  3741.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_USEREX_REG);
  3742.     }
  3743.     if (fToRegister & AFX_WNDCOMMCTL_DATE_REG)
  3744.     {
  3745.         init.dwICC = ICC_DATE_CLASSES;
  3746.         fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_DATE_REG);
  3747.     }
  3748.  
  3749.     // save new state of registered controls
  3750.     pModuleState->m_fRegisteredClasses |= fRegisteredClasses;
  3751.  
  3752.     // special case for all common controls registered, turn on AFX_WNDCOMMCTLS_REG
  3753.     if ((pModuleState->m_fRegisteredClasses & AFX_WIN95CTLS_MASK) == AFX_WIN95CTLS_MASK)
  3754.     {
  3755.         pModuleState->m_fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
  3756.         fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
  3757.     }
  3758.  
  3759.     // must have registered at least as mamy classes as requested
  3760.     return (fToRegister & fRegisteredClasses) == fToRegister;
  3761. }
  3762.  
  3763. /////////////////////////////////////////////////////////////////////////////
  3764. // CFrameWnd (here for library granularity)
  3765.  
  3766. BOOL CWnd::IsFrameWnd() const
  3767. {
  3768.     return FALSE;
  3769. }
  3770.  
  3771. BOOL CFrameWnd::IsFrameWnd() const
  3772. {
  3773.     return TRUE;
  3774. }
  3775.  
  3776. BOOL CFrameWnd::IsTracking() const
  3777. {
  3778.     return m_nIDTracking != 0 &&
  3779.         m_nIDTracking != AFX_IDS_HELPMODEMESSAGE &&
  3780.         m_nIDTracking != AFX_IDS_IDLEMESSAGE;
  3781. }
  3782.  
  3783. /////////////////////////////////////////////////////////////////////////////
  3784. // CTL3D support
  3785.  
  3786. #ifndef _AFX_NO_CTL3D_SUPPORT
  3787.  
  3788. // Use SubclassCtl3d to add CTL3D support to an already subclassed control
  3789. // Usually only necessary if the control does not have one of the standard
  3790. //  Windows class names.
  3791. BOOL CWnd::SubclassCtl3d(int nControlType)
  3792. {
  3793.     ASSERT(!afxContextIsDLL);   // Should only be called by apps
  3794.  
  3795.     if (afxContextIsDLL)
  3796.         return FALSE;
  3797.  
  3798.     ASSERT(m_hWnd != NULL);
  3799.  
  3800.     _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  3801.     if (nControlType == -1)
  3802.     {
  3803.         if (pCtl3dState->m_pfnSubclassCtl != NULL)
  3804.             return (*pCtl3dState->m_pfnSubclassCtl)(m_hWnd);
  3805.     }
  3806.     else
  3807.     {
  3808.         if (pCtl3dState->m_pfnSubclassCtlEx != NULL)
  3809.             return (*pCtl3dState->m_pfnSubclassCtlEx)(m_hWnd, nControlType);
  3810.     }
  3811.     return FALSE;
  3812. }
  3813.  
  3814. // Use SubclassDlg3d to add CTL3D support to an entire window.
  3815. //  Any windows created on the window will be automatically subclassed.
  3816. BOOL CWnd::SubclassDlg3d(DWORD dwMask)
  3817. {
  3818.     ASSERT(!afxContextIsDLL);   // Should only be called by apps
  3819.  
  3820.     if (afxContextIsDLL)
  3821.         return FALSE;
  3822.  
  3823.     ASSERT(m_hWnd != NULL);
  3824.  
  3825.     _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
  3826.     if (pCtl3dState->m_pfnSubclassDlgEx != NULL)
  3827.         return pCtl3dState->m_pfnSubclassDlgEx(m_hWnd, dwMask);
  3828.     return FALSE;
  3829. }
  3830.  
  3831. #endif //!_AFX_NO_CTL3D_SUPPORT
  3832.  
  3833. //this function can't be inlined because of _afxShell
  3834. void CWnd::DragAcceptFiles(BOOL bAccept)
  3835. {
  3836.     ASSERT(::IsWindow(m_hWnd));
  3837.     ::DragAcceptFiles(m_hWnd, bAccept);
  3838. }
  3839.  
  3840. /////////////////////////////////////////////////////////////////////////////
  3841. // Extra CWnd support for dynamic subclassing of controls
  3842.  
  3843. BOOL CWnd::SubclassWindow(HWND hWnd)
  3844. {
  3845.     if (!Attach(hWnd))
  3846.         return FALSE;
  3847.  
  3848.     // allow any other subclassing to occur
  3849.     PreSubclassWindow();
  3850.  
  3851.     // now hook into the AFX WndProc
  3852.     WNDPROC* lplpfn = GetSuperWndProcAddr();
  3853.     WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC,
  3854.         (DWORD)AfxGetAfxWndProc());
  3855.     ASSERT(oldWndProc != (WNDPROC)AfxGetAfxWndProc());
  3856.  
  3857.     if (*lplpfn == NULL)
  3858.         *lplpfn = oldWndProc;   // the first control of that type created
  3859. #ifdef _DEBUG
  3860.     else if (*lplpfn != oldWndProc)
  3861.     {
  3862.         TRACE0("Error: Trying to use SubclassWindow with incorrect CWnd\n");
  3863.         TRACE0("\tderived class.\n");
  3864.         TRACE3("\thWnd = $%04X (nIDC=$%04X) is not a %hs.\n", (UINT)hWnd,
  3865.             _AfxGetDlgCtrlID(hWnd), GetRuntimeClass()->m_lpszClassName);
  3866.         ASSERT(FALSE);
  3867.         // undo the subclassing if continuing after assert
  3868.         ::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)oldWndProc);
  3869.     }
  3870. #endif
  3871.  
  3872.     return TRUE;
  3873. }
  3874.  
  3875. BOOL CWnd::SubclassDlgItem(UINT nID, CWnd* pParent)
  3876. {
  3877.     ASSERT(pParent != NULL);
  3878.     ASSERT(::IsWindow(pParent->m_hWnd));
  3879.  
  3880.     // check for normal dialog control first
  3881.     HWND hWndControl = ::GetDlgItem(pParent->m_hWnd, nID);
  3882.     if (hWndControl != NULL)
  3883.         return SubclassWindow(hWndControl);
  3884.  
  3885. #ifndef _AFX_NO_OCC_SUPPORT
  3886.     if (pParent->m_pCtrlCont != NULL)
  3887.     {
  3888.         // normal dialog control not found
  3889.         COleControlSite* pSite = pParent->m_pCtrlCont->FindItem(nID);
  3890.         if (pSite != NULL)
  3891.         {
  3892.             ASSERT(pSite->m_hWnd != NULL);
  3893.             VERIFY(SubclassWindow(pSite->m_hWnd));
  3894.  
  3895. #ifndef _AFX_NO_OCC_SUPPORT
  3896.             // If the control has reparented itself (e.g., invisible control),
  3897.             // make sure that the CWnd gets properly wired to its control site.
  3898.             if (pParent->m_hWnd != ::GetParent(pSite->m_hWnd))
  3899.                 AttachControlSite(pParent);
  3900. #endif //!_AFX_NO_OCC_SUPPORT
  3901.  
  3902.             return TRUE;
  3903.         }
  3904.     }
  3905. #endif
  3906.  
  3907.     return FALSE;   // control not found
  3908. }
  3909.  
  3910. HWND CWnd::UnsubclassWindow()
  3911. {
  3912.     ASSERT(::IsWindow(m_hWnd));
  3913.  
  3914.     // set WNDPROC back to original value
  3915.     WNDPROC* lplpfn = GetSuperWndProcAddr();
  3916.     SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)*lplpfn);
  3917.     *lplpfn = NULL;
  3918.  
  3919.     // and Detach the HWND from the CWnd object
  3920.     return Detach();
  3921. }
  3922.  
  3923. ////////////////////////////////////////////////////////////////////////////
  3924. // out-of-line inlines for binary compatibility
  3925.  
  3926. #ifdef _AFXDLL
  3927. #ifndef _DEBUG
  3928.  
  3929. CPoint::CPoint(POINT initPt)
  3930.     { *(POINT*)this = initPt; }
  3931.  
  3932. #endif
  3933. #endif
  3934.  
  3935. #ifdef AFX_INIT_SEG
  3936. #pragma code_seg(AFX_INIT_SEG)
  3937. #endif
  3938.  
  3939. IMPLEMENT_DYNCREATE(CWnd, CCmdTarget)
  3940.  
  3941. IMPLEMENT_DYNCREATE(CTempWnd, CWnd);
  3942.  
  3943. #pragma warning(disable: 4074)
  3944. #pragma init_seg(compiler)
  3945. IMPLEMENT_FIXED_ALLOC(CTempWnd, 64);
  3946.  
  3947. /////////////////////////////////////////////////////////////////////////////
  3948.