home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / WINFRM.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-11  |  62.3 KB  |  2,306 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 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. #include <dde.h>        // for DDE execute shell requests
  13.  
  14. #ifdef AFX_CORE4_SEG
  15. #pragma code_seg(AFX_CORE4_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #define new DEBUG_NEW
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CRect for creating windows with the default position/size
  27.  
  28. const AFX_DATADEF CRect CFrameWnd::rectDefault(
  29.     CW_USEDEFAULT, CW_USEDEFAULT,
  30.     0 /* 2*CW_USEDEFAULT */, 0 /* 2*CW_USEDEFAULT */);
  31.  
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CFrameWnd
  34.  
  35. // register for Windows 95 or Windows NT 3.51
  36. static UINT nMsgMouseWheel =
  37.    (((::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion()) == 4)) ||
  38.      (!(::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion()) == 3)))
  39.      ? ::RegisterWindowMessage(MSH_MOUSEWHEEL) : 0;
  40.  
  41. BEGIN_MESSAGE_MAP(CFrameWnd, CWnd)
  42.     //{{AFX_MSG_MAP(CFrameWnd)
  43.     ON_WM_INITMENUPOPUP()
  44.     ON_WM_MENUSELECT()
  45.     ON_MESSAGE(WM_POPMESSAGESTRING, OnPopMessageString)
  46.     ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString)
  47.     ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
  48.     ON_WM_ENTERIDLE()
  49.     ON_WM_HSCROLL()
  50.     ON_WM_VSCROLL()
  51.     ON_WM_SETFOCUS()
  52.     ON_WM_CREATE()
  53.     ON_WM_DESTROY()
  54.     ON_WM_CLOSE()
  55.     ON_WM_SIZE()
  56.     ON_WM_ERASEBKGND()
  57.     ON_WM_ACTIVATE()
  58.     ON_WM_NCACTIVATE()
  59.     ON_WM_SYSCOMMAND()
  60.     ON_WM_DROPFILES()
  61.     ON_WM_QUERYENDSESSION()
  62.     ON_WM_ENDSESSION()
  63.     ON_WM_SETCURSOR()
  64.     ON_WM_ENABLE()
  65.     // OLE palette support
  66.     ON_WM_QUERYNEWPALETTE()
  67.     ON_WM_PALETTECHANGED()
  68.     ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
  69.     ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
  70.     ON_MESSAGE(WM_ACTIVATETOPLEVEL, OnActivateTopLevel)
  71.     // turning on and off standard frame gadgetry
  72.     ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateControlBarMenu)
  73.     ON_COMMAND_EX(ID_VIEW_STATUS_BAR, OnBarCheck)
  74.     ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLBAR, OnUpdateControlBarMenu)
  75.     ON_COMMAND_EX(ID_VIEW_TOOLBAR, OnBarCheck)
  76.     // turning on and off standard mode indicators
  77.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_CAPS, OnUpdateKeyIndicator)
  78.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_NUM, OnUpdateKeyIndicator)
  79.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_SCRL, OnUpdateKeyIndicator)
  80.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_KANA, OnUpdateKeyIndicator)
  81.     // standard help handling
  82.     ON_UPDATE_COMMAND_UI(ID_CONTEXT_HELP, OnUpdateContextHelp)
  83.     // toolbar "tooltip" notification
  84.     ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
  85.     ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
  86.     //}}AFX_MSG_MAP
  87. #ifndef _MAC
  88.     // message handling for standard DDE commands
  89.     ON_MESSAGE(WM_DDE_INITIATE, OnDDEInitiate)
  90.     ON_MESSAGE(WM_DDE_EXECUTE, OnDDEExecute)
  91.     ON_MESSAGE(WM_DDE_TERMINATE, OnDDETerminate)
  92.     ON_REGISTERED_MESSAGE(nMsgMouseWheel, OnRegisteredMouseWheel)
  93. #else
  94.     // special handling of app activation
  95.     ON_WM_ACTIVATEAPP()
  96.     // special handling for uncovered areas of the client area caused by
  97.     // Macintosh sizebox
  98.     ON_WM_PAINT()
  99. #endif
  100. END_MESSAGE_MAP()
  101.  
  102. /////////////////////////////////////////////////////////////////////////////
  103. // CFrameWnd construction/destruction
  104.  
  105. CFrameWnd::CFrameWnd()
  106. {
  107.     ASSERT(m_hWnd == NULL);
  108.  
  109.     m_nWindow = -1;                 // unknown window ID
  110.     m_bAutoMenuEnable = TRUE;       // auto enable on by default
  111.     m_lpfnCloseProc = NULL;
  112.     m_hMenuDefault = NULL;
  113.     m_hAccelTable = NULL;
  114.     m_nIDHelp = 0;
  115.     m_nIDTracking = 0;
  116.     m_nIDLastMessage = 0;
  117.     m_pViewActive = NULL;
  118.  
  119.     m_cModalStack = 0;              // initialize modality support
  120.     m_phWndDisable = NULL;
  121.     m_pNotifyHook = NULL;
  122.     m_hMenuAlt = NULL;
  123.     m_nIdleFlags = 0;               // no idle work at start
  124.     m_rectBorder.SetRectEmpty();
  125.  
  126.     m_bHelpMode = HELP_INACTIVE;    // not in Shift+F1 help mode
  127.     m_dwPromptContext = 0;
  128.  
  129.     m_pNextFrameWnd = NULL;         // not in list yet
  130.  
  131.     m_bInRecalcLayout = FALSE;
  132.     m_pFloatingFrameClass = NULL;
  133.     m_nShowDelay = -1;              // no delay pending
  134.  
  135.     AddFrameWnd();
  136. }
  137.  
  138. CFrameWnd::~CFrameWnd()
  139. {
  140.     RemoveFrameWnd();
  141.     if (m_phWndDisable != NULL)
  142.         delete[] (void*)m_phWndDisable;
  143. }
  144.  
  145. void CFrameWnd::AddFrameWnd()
  146. {
  147.     // hook it into the CFrameWnd list
  148.     AFX_MODULE_THREAD_STATE* pState = _AFX_CMDTARGET_GETSTATE()->m_thread;
  149.     pState->m_frameList.AddHead(this);
  150. }
  151.  
  152. void CFrameWnd::RemoveFrameWnd()
  153. {
  154.     // remove this frame window from the list of frame windows
  155.     AFX_MODULE_THREAD_STATE* pState = _AFX_CMDTARGET_GETSTATE()->m_thread;
  156.     pState->m_frameList.Remove(this);
  157. }
  158.  
  159. /////////////////////////////////////////////////////////////////////////////
  160. // Special processing etc
  161.  
  162. BOOL CFrameWnd::LoadAccelTable(LPCTSTR lpszResourceName)
  163. {
  164.     ASSERT(m_hAccelTable == NULL);  // only do once
  165.     ASSERT(lpszResourceName != NULL);
  166.  
  167.     HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_ACCELERATOR);
  168.     m_hAccelTable = ::LoadAccelerators(hInst, lpszResourceName);
  169.     return (m_hAccelTable != NULL);
  170. }
  171.  
  172. HACCEL CFrameWnd::GetDefaultAccelerator()
  173. {
  174.     // use document specific accelerator table over m_hAccelTable
  175.     HACCEL hAccelTable = m_hAccelTable;
  176.     HACCEL hAccel;
  177.     CDocument* pDoc = GetActiveDocument();
  178.     if (pDoc != NULL && (hAccel = pDoc->GetDefaultAccelerator()) != NULL)
  179.         hAccelTable = hAccel;
  180.  
  181.     return hAccelTable;
  182. }
  183.  
  184. BOOL CFrameWnd::PreTranslateMessage(MSG* pMsg)
  185. {
  186.     // check for special cancel modes for combo boxes
  187.     if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_NCLBUTTONDOWN)
  188.         AfxCancelModes(pMsg->hwnd);    // filter clicks
  189.  
  190.     // allow tooltip messages to be filtered
  191.     if (CWnd::PreTranslateMessage(pMsg))
  192.         return TRUE;
  193.  
  194. #ifndef _AFX_NO_OLE_SUPPORT
  195.     // allow hook to consume message
  196.     if (m_pNotifyHook != NULL && m_pNotifyHook->OnPreTranslateMessage(pMsg))
  197.         return TRUE;
  198. #endif
  199.  
  200.     if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
  201.     {
  202.         // finally, translate the message
  203.         HACCEL hAccel = GetDefaultAccelerator();
  204.         return hAccel != NULL &&  ::TranslateAccelerator(m_hWnd, hAccel, pMsg);
  205.     }
  206.     return FALSE;
  207. }
  208.  
  209. void CFrameWnd::PostNcDestroy()
  210. {
  211.     // default for frame windows is to allocate them on the heap
  212.     //  the default post-cleanup is to 'delete this'.
  213.     // never explicitly call 'delete' on a CFrameWnd, use DestroyWindow instead
  214.     delete this;
  215. }
  216.  
  217. void CFrameWnd::OnPaletteChanged(CWnd* pFocusWnd)
  218. {
  219.     CWnd::OnPaletteChanged(pFocusWnd);
  220. #ifndef _AFX_NO_OLE_SUPPORT
  221.     if (m_pNotifyHook != NULL)
  222.         m_pNotifyHook->OnPaletteChanged(pFocusWnd);
  223. #endif
  224. }
  225.  
  226. BOOL CFrameWnd::OnQueryNewPalette()
  227. {
  228. #ifndef _AFX_NO_OLE_SUPPORT
  229.     if (m_pNotifyHook != NULL && m_pNotifyHook->OnQueryNewPalette())
  230.         return TRUE;
  231. #endif
  232.     return CWnd::OnQueryNewPalette();
  233. }
  234.  
  235. /////////////////////////////////////////////////////////////////////////////
  236. // CFrameWnd support for context sensitive help.
  237.  
  238. void CFrameWnd::ExitHelpMode()
  239. {
  240.     // if not in help mode currently, this is a no-op
  241.     if (!m_bHelpMode)
  242.         return;
  243.  
  244.     // only post new WM_EXITHELPMODE message if one doesn't already exist
  245.     //  in the queue.
  246.     MSG msg;
  247.     if (!::PeekMessage(&msg, m_hWnd, WM_EXITHELPMODE, WM_EXITHELPMODE,
  248.         PM_REMOVE|PM_NOYIELD))
  249.     {
  250.         VERIFY(::PostMessage(m_hWnd, WM_EXITHELPMODE, 0, 0));
  251.     }
  252.  
  253.     // release capture if this window has it
  254.     if (::GetCapture() == m_hWnd)
  255.         ReleaseCapture();
  256.  
  257.     CFrameWnd* pFrameWnd = GetTopLevelFrame();
  258.     ASSERT_VALID(pFrameWnd);
  259.     pFrameWnd->m_bHelpMode = m_bHelpMode = HELP_INACTIVE;
  260.     PostMessage(WM_KICKIDLE);   // trigger idle update
  261. }
  262.  
  263. BOOL CFrameWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  264. {
  265.     CFrameWnd* pFrameWnd = GetTopLevelFrame();
  266.     ASSERT_VALID(pFrameWnd);
  267.     if (pFrameWnd->m_bHelpMode)
  268.     {
  269.         SetCursor(afxData.hcurHelp);
  270.         return TRUE;
  271.     }
  272.     return CWnd::OnSetCursor(pWnd, nHitTest, message);
  273. }
  274.  
  275. LRESULT CFrameWnd::OnCommandHelp(WPARAM, LPARAM lParam)
  276. {
  277.     if (lParam == 0)
  278.     {
  279.         if (IsTracking())
  280.             lParam = HID_BASE_COMMAND+m_nIDTracking;
  281.         else
  282.             lParam = HID_BASE_RESOURCE+m_nIDHelp;
  283.     }
  284.     if (lParam != 0)
  285.     {
  286.         AfxGetApp()->WinHelp(lParam);
  287.         return TRUE;
  288.     }
  289.     return FALSE;
  290. }
  291.  
  292. LRESULT CFrameWnd::OnHelpHitTest(WPARAM, LPARAM)
  293. {
  294.     if (m_nIDHelp != 0)
  295.         return HID_BASE_RESOURCE+m_nIDHelp;
  296.     else
  297.         return 0;
  298. }
  299.  
  300. BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
  301.     // return TRUE if command invocation was attempted
  302. {
  303.     HWND hWndCtrl = (HWND)lParam;
  304.     UINT nID = LOWORD(wParam);
  305.  
  306.     CFrameWnd* pFrameWnd = GetTopLevelFrame();
  307.     ASSERT_VALID(pFrameWnd);
  308.     if (pFrameWnd->m_bHelpMode && hWndCtrl == NULL &&
  309.         nID != ID_HELP && nID != ID_DEFAULT_HELP && nID != ID_CONTEXT_HELP)
  310.     {
  311.         // route as help
  312.         if (!SendMessage(WM_COMMANDHELP, 0, HID_BASE_COMMAND+nID))
  313.             SendMessage(WM_COMMAND, ID_DEFAULT_HELP);
  314.         return TRUE;
  315.     }
  316.  
  317.     // route as normal command
  318.     return CWnd::OnCommand(wParam, lParam);
  319. }
  320.  
  321. /////////////////////////////////////////////////////////////////////////////
  322. // CFrameWnd support for modality
  323.  
  324. BOOL AFXAPI AfxIsDescendant(HWND hWndParent, HWND hWndChild)
  325.     // helper for detecting whether child descendent of parent
  326.     //  (works with owned popups as well)
  327. {
  328.     ASSERT(::IsWindow(hWndParent));
  329.     ASSERT(::IsWindow(hWndChild));
  330.  
  331.     do
  332.     {
  333.         if (hWndParent == hWndChild)
  334.             return TRUE;
  335.  
  336.         hWndChild = AfxGetParentOwner(hWndChild);
  337.     } while (hWndChild != NULL);
  338.  
  339.     return FALSE;
  340. }
  341.  
  342. void CFrameWnd::BeginModalState()
  343. {
  344.     ASSERT(m_hWnd != NULL);
  345.     ASSERT(::IsWindow(m_hWnd));
  346.  
  347.     // allow stacking, but don't do anything
  348.     if (++m_cModalStack > 1)
  349.         return;
  350.  
  351.     // determine top-level parent, since that is the true parent of any
  352.     //  modeless windows anyway...
  353.     CWnd* pParent = GetTopLevelParent();
  354.  
  355.     // first count all windows that need to be disabled
  356.     UINT nCount = 0;
  357.     HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
  358.     while (hWnd != NULL)
  359.     {
  360.         if (::IsWindowEnabled(hWnd) &&
  361.             CWnd::FromHandlePermanent(hWnd) != NULL &&
  362.             AfxIsDescendant(pParent->m_hWnd, hWnd) &&
  363.             ::SendMessage(hWnd, WM_DISABLEMODAL, 0, 0) == 0)
  364.         {
  365.             ++nCount;
  366.         }
  367.         hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  368.     }
  369.     if (nCount == 0)
  370.         return;
  371.  
  372.     m_phWndDisable = new HWND[nCount+1];
  373.  
  374.     // disable all windows connected to this frame (and add them to the list)
  375.     UINT nIndex = 0;
  376.     hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
  377.     while (hWnd != NULL)
  378.     {
  379.         if (::IsWindowEnabled(hWnd) &&
  380.             CWnd::FromHandlePermanent(hWnd) != NULL &&
  381.             AfxIsDescendant(pParent->m_hWnd, hWnd) &&
  382.             ::SendMessage(hWnd, WM_DISABLEMODAL, 0, 0) == 0)
  383.         {
  384.             ::EnableWindow(hWnd, FALSE);
  385.             ASSERT(nIndex < nCount);
  386.             m_phWndDisable[nIndex] = hWnd;
  387.             ++nIndex;
  388.         }
  389.         hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  390.     }
  391.  
  392.     // terminate the list with a NULL
  393.     ASSERT(nIndex < nCount+1);
  394.     m_phWndDisable[nIndex] = NULL;
  395. }
  396.  
  397. void CFrameWnd::EndModalState()
  398. {
  399.     // pop one off the stack (don't undo modalness unless stack is down to zero)
  400.     if (m_cModalStack == 0 || --m_cModalStack > 0 || m_phWndDisable == NULL)
  401.         return;
  402.  
  403.     // enable all the windows disabled by BeginModalState
  404.     ASSERT(m_phWndDisable != NULL);
  405.     UINT nIndex = 0;
  406.     while (m_phWndDisable[nIndex] != NULL)
  407.     {
  408.         ASSERT(m_phWndDisable[nIndex] != NULL);
  409.         if (::IsWindow(m_phWndDisable[nIndex]))
  410.             ::EnableWindow(m_phWndDisable[nIndex], TRUE);
  411.         ++nIndex;
  412.     }
  413.     delete[] (void*)m_phWndDisable;
  414.     m_phWndDisable = NULL;
  415. }
  416.  
  417. void CFrameWnd::ShowOwnedWindows(BOOL bShow)
  418. {
  419.     // walk through all top-level windows
  420.     HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
  421.     while (hWnd != NULL)
  422.     {
  423.         CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
  424.         if (pWnd != NULL && m_hWnd != hWnd && AfxIsDescendant(m_hWnd, hWnd))
  425.         {
  426.             DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
  427.             if (!bShow && (dwStyle & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
  428.             {
  429.                 ::ShowWindow(hWnd, SW_HIDE);
  430.                 pWnd->m_nFlags |= WF_TEMPHIDE;
  431.             }
  432.             else if (bShow && (dwStyle & (WS_VISIBLE|WS_DISABLED)) == 0 &&
  433.                 (pWnd->m_nFlags & WF_TEMPHIDE))
  434.             {
  435.                 ::ShowWindow(hWnd, SW_SHOWNOACTIVATE);
  436.                 pWnd->m_nFlags &= ~WF_TEMPHIDE;
  437.             }
  438.         }
  439.         hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  440.     }
  441. }
  442.  
  443. void CFrameWnd::OnEnable(BOOL bEnable)
  444. {
  445.     if (bEnable && (m_nFlags & WF_STAYDISABLED))
  446.     {
  447.         // Work around for MAPI support. This makes sure the main window
  448.         // remains disabled even when the mail system is booting.
  449.         EnableWindow(FALSE);
  450.         ::SetFocus(NULL);
  451.         return;
  452.     }
  453.  
  454.     // only for top-level (and non-owned) windows
  455.     if (GetParent() != NULL)
  456.         return;
  457.  
  458.     // this causes modal dialogs to be "truly modal"
  459.     if (!bEnable && !InModalState())
  460.     {
  461.         ASSERT((m_nFlags & WF_MODALDISABLE) == 0);
  462.         m_nFlags |= WF_MODALDISABLE;
  463.         BeginModalState();
  464.     }
  465.     else if (bEnable && (m_nFlags & WF_MODALDISABLE))
  466.     {
  467.         m_nFlags &= ~WF_MODALDISABLE;
  468.         EndModalState();
  469.  
  470.         // cause normal focus logic to kick in
  471.         if (::GetActiveWindow() == m_hWnd)
  472.             SendMessage(WM_ACTIVATE, WA_ACTIVE);
  473.     }
  474.  
  475.     // force WM_NCACTIVATE because Windows may think it is unecessary
  476.     if (bEnable && (m_nFlags & WF_STAYACTIVE))
  477.         SendMessage(WM_NCACTIVATE, TRUE);
  478.     // force WM_NCACTIVATE for floating windows too
  479.     NotifyFloatingWindows(bEnable ? FS_ENABLE : FS_DISABLE);
  480. }
  481.  
  482. void CFrameWnd::NotifyFloatingWindows(DWORD dwFlags)
  483. {
  484.     ASSERT_VALID(this);
  485.     ASSERT(m_hWnd != NULL);
  486.  
  487.     // get top level parent frame window first unless this is a child window
  488.     CFrameWnd* pParent = (GetStyle() & WS_CHILD) ? this : GetTopLevelFrame();
  489.     ASSERT(pParent != NULL);
  490.     if (dwFlags & (FS_DEACTIVATE|FS_ACTIVATE))
  491.     {
  492.         // update parent window activation state
  493.         BOOL bActivate = !(dwFlags & FS_DEACTIVATE);
  494.         BOOL bEnabled = pParent->IsWindowEnabled();
  495.  
  496.         if (bActivate && bEnabled && pParent != this)
  497.         {
  498.             // Excel will try to Activate itself when it receives a
  499.             // WM_NCACTIVATE so we need to keep it from doing that here.
  500.             m_nFlags |= WF_KEEPMINIACTIVE;
  501.             pParent->SendMessage(WM_NCACTIVATE, TRUE);
  502.             m_nFlags &= ~WF_KEEPMINIACTIVE;
  503.         }
  504.         else
  505.         {
  506.             pParent->SendMessage(WM_NCACTIVATE, FALSE);
  507.         }
  508.     }
  509.  
  510.     // then update the state of all floating windows owned by the parent
  511.     HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
  512.     while (hWnd != NULL)
  513.     {
  514.         if (AfxIsDescendant(pParent->m_hWnd, hWnd))
  515.             ::SendMessage(hWnd, WM_FLOATSTATUS, dwFlags, 0);
  516.         hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  517.     }
  518. }
  519.  
  520. /////////////////////////////////////////////////////////////////////////////
  521. // CFrameWnd second phase creation
  522.  
  523. BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
  524. {
  525.     if (cs.lpszClass == NULL)
  526.     {
  527.         if (!AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG))
  528.             return FALSE;
  529.  
  530.         cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
  531.     }
  532.  
  533.     if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
  534.         cs.style |= FWS_PREFIXTITLE;
  535.  
  536.     if (afxData.bWin4)
  537.         cs.dwExStyle |= WS_EX_CLIENTEDGE;
  538.  
  539.     return TRUE;
  540. }
  541.  
  542. BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
  543.     LPCTSTR lpszWindowName,
  544.     DWORD dwStyle,
  545.     const RECT& rect,
  546.     CWnd* pParentWnd,
  547.     LPCTSTR lpszMenuName,
  548.     DWORD dwExStyle,
  549.     CCreateContext* pContext)
  550. {
  551.     HMENU hMenu = NULL;
  552.     if (lpszMenuName != NULL)
  553.     {
  554.         // load in a menu that will get destroyed when window gets destroyed
  555.         HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU);
  556.         if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)
  557.         {
  558.             TRACE0("Warning: failed to load menu for CFrameWnd.\n");
  559.             PostNcDestroy();            // perhaps delete the C++ object
  560.             return FALSE;
  561.         }
  562.     }
  563.  
  564.     m_strTitle = lpszWindowName;    // save title for later
  565.  
  566. #ifdef _MAC
  567.     dwExStyle |= WS_EX_FORCESIZEBOX;
  568. #endif
  569.  
  570.     if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
  571.         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  572.         pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))
  573.     {
  574.         TRACE0("Warning: failed to create CFrameWnd.\n");
  575.         if (hMenu != NULL)
  576.             DestroyMenu(hMenu);
  577.         return FALSE;
  578.     }
  579.  
  580. #ifdef _MAC
  581.     CMenu* pMenu = GetSystemMenu(FALSE);
  582.     if (pMenu != NULL)
  583.     {
  584.         CString strAbout;
  585.         TCHAR szFormat[256];
  586.         LPCTSTR pszAppName = AfxGetAppName();
  587.  
  588.         // a statically linked dialog-based app might not have included afxres.rc
  589.         if (!AfxLoadString(AFX_IDS_ABOUT, szFormat))
  590.             lstrcpy(szFormat, _T("About %1..."));
  591.  
  592.         AfxFormatStrings(strAbout, szFormat, &pszAppName, 1);
  593.         pMenu->ModifyMenu(0, MF_BYPOSITION | MF_STRING, ID_APP_ABOUT, strAbout);
  594.     }
  595. #endif
  596.  
  597.     return TRUE;
  598. }
  599.  
  600. CWnd* CFrameWnd::CreateView(CCreateContext* pContext, UINT nID)
  601. {
  602.     ASSERT(m_hWnd != NULL);
  603.     ASSERT(::IsWindow(m_hWnd));
  604.     ASSERT(pContext != NULL);
  605.     ASSERT(pContext->m_pNewViewClass != NULL);
  606.  
  607.     // Note: can be a CWnd with PostNcDestroy self cleanup
  608.     CWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();
  609.     if (pView == NULL)
  610.     {
  611.         TRACE1("Warning: Dynamic create of view type %hs failed.\n",
  612.             pContext->m_pNewViewClass->m_lpszClassName);
  613.         return NULL;
  614.     }
  615.     ASSERT_KINDOF(CWnd, pView);
  616.  
  617.     // views are always created with a border!
  618.     if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
  619.         CRect(0,0,0,0), this, nID, pContext))
  620.     {
  621.         TRACE0("Warning: could not create view for frame.\n");
  622.         return NULL;        // can't continue without a view
  623.     }
  624.  
  625.     if (afxData.bWin4 && (pView->GetExStyle() & WS_EX_CLIENTEDGE))
  626.     {
  627.         // remove the 3d style from the frame, since the view is
  628.         //  providing it.
  629.         // make sure to recalc the non-client area
  630.         ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);
  631.     }
  632.     return pView;
  633. }
  634.  
  635. BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext)
  636. {
  637.     // default create client will create a view if asked for it
  638.     if (pContext != NULL && pContext->m_pNewViewClass != NULL)
  639.     {
  640.         if (CreateView(pContext, AFX_IDW_PANE_FIRST) == NULL)
  641.             return FALSE;
  642.     }
  643.     return TRUE;
  644. }
  645.  
  646. int CFrameWnd::OnCreate(LPCREATESTRUCT lpcs)
  647. {
  648.     CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;
  649.     return OnCreateHelper(lpcs, pContext);
  650. }
  651.  
  652. int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext)
  653. {
  654.     if (CWnd::OnCreate(lpcs) == -1)
  655.         return -1;
  656.  
  657.     // create special children first
  658.     if (!OnCreateClient(lpcs, pContext))
  659.     {
  660.         TRACE0("Failed to create client pane/view for frame.\n");
  661.         return -1;
  662.     }
  663.  
  664.     // post message for initial message string
  665.     PostMessage(WM_SETMESSAGESTRING, AFX_IDS_IDLEMESSAGE);
  666.  
  667.     // make sure the child windows have been properly sized
  668.     RecalcLayout();
  669.  
  670.     return 0;   // create ok
  671. }
  672.  
  673. LPCTSTR CFrameWnd::GetIconWndClass(DWORD dwDefaultStyle, UINT nIDResource)
  674. {
  675.     ASSERT_VALID_IDR(nIDResource);
  676.     HINSTANCE hInst = AfxFindResourceHandle(
  677.         MAKEINTRESOURCE(nIDResource), RT_GROUP_ICON);
  678.     HICON hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDResource));
  679.     if (hIcon != NULL)
  680.     {
  681.         CREATESTRUCT cs;
  682.         memset(&cs, 0, sizeof(CREATESTRUCT));
  683.         cs.style = dwDefaultStyle;
  684.         PreCreateWindow(cs);
  685.             // will fill lpszClassName with default WNDCLASS name
  686.             // ignore instance handle from PreCreateWindow.
  687.  
  688.         WNDCLASS wndcls;
  689.         if (cs.lpszClass != NULL &&
  690.             GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wndcls) &&
  691.             wndcls.hIcon != hIcon)
  692.         {
  693.             // register a very similar WNDCLASS
  694.             return AfxRegisterWndClass(wndcls.style,
  695.                 wndcls.hCursor, wndcls.hbrBackground, hIcon);
  696.         }
  697.     }
  698.     return NULL;        // just use the default
  699. }
  700.  
  701. BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
  702.     CWnd* pParentWnd, CCreateContext* pContext)
  703. {
  704.     // only do this once
  705.     ASSERT_VALID_IDR(nIDResource);
  706.     ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
  707.  
  708.     m_nIDHelp = nIDResource;    // ID for help context (+HID_BASE_RESOURCE)
  709.  
  710.     CString strFullString;
  711.     if (strFullString.LoadString(nIDResource))
  712.         AfxExtractSubString(m_strTitle, strFullString, 0);    // first sub-string
  713.  
  714.     if (!AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG))
  715.         return FALSE;
  716.  
  717.     // attempt to create the window
  718.     LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
  719.     LPCTSTR lpszTitle = m_strTitle;
  720.     if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault,
  721.       pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
  722.     {
  723.         return FALSE;   // will self destruct on failure normally
  724.     }
  725.  
  726.     // save the default menu handle
  727.     ASSERT(m_hWnd != NULL);
  728.     m_hMenuDefault = ::GetMenu(m_hWnd);
  729.  
  730.     // load accelerator resource
  731.     LoadAccelTable(MAKEINTRESOURCE(nIDResource));
  732.  
  733.     if (pContext == NULL)   // send initial update
  734.         SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
  735.  
  736.     return TRUE;
  737. }
  738.  
  739. void CFrameWnd::OnUpdateFrameMenu(HMENU hMenuAlt)
  740. {
  741.     if (hMenuAlt == NULL)
  742.     {
  743.         // attempt to get default menu from document
  744.         CDocument* pDoc = GetActiveDocument();
  745.         if (pDoc != NULL)
  746.             hMenuAlt = pDoc->GetDefaultMenu();
  747.         // use default menu stored in frame if none from document
  748.         if (hMenuAlt == NULL)
  749.             hMenuAlt = m_hMenuDefault;
  750.     }
  751.     // finally, set the menu
  752.     ::SetMenu(m_hWnd, hMenuAlt);
  753. }
  754.  
  755. void CFrameWnd::InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible)
  756. {
  757.     // if the frame does not have an active view, set to first pane
  758.     CView* pView = NULL;
  759.     if (GetActiveView() == NULL)
  760.     {
  761.         CWnd* pWnd = GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
  762.         if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CView)))
  763.         {
  764.             pView = (CView*)pWnd;
  765.             SetActiveView(pView, FALSE);
  766.         }
  767.     }
  768.  
  769.     if (bMakeVisible)
  770.     {
  771.         // send initial update to all views (and other controls) in the frame
  772.         SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
  773.  
  774.         // give view a chance to save the focus (CFormView needs this)
  775.         if (pView != NULL)
  776.             pView->OnActivateFrame(WA_INACTIVE, this);
  777.  
  778.         // finally, activate the frame
  779.         // (send the default show command unless the main desktop window)
  780.         int nCmdShow = -1;      // default
  781.         CWinApp* pApp = AfxGetApp();
  782.         if (this == pApp->m_pMainWnd)
  783.         {
  784.             nCmdShow = pApp->m_nCmdShow; // use the parameter from WinMain
  785.             pApp->m_nCmdShow = -1; // set to default after first time
  786.         }
  787.         ActivateFrame(nCmdShow);
  788.         if (pView != NULL)
  789.             pView->OnActivateView(TRUE, pView, pView);
  790.     }
  791.  
  792.     // update frame counts and frame title (may already have been visible)
  793.     if (pDoc != NULL)
  794.         pDoc->UpdateFrameCounts();
  795.     OnUpdateFrameTitle(TRUE);
  796. }
  797.  
  798. /////////////////////////////////////////////////////////////////////////////
  799. // CFrameWnd closing down
  800.  
  801. void CFrameWnd::OnClose()
  802. {
  803.     if (m_lpfnCloseProc != NULL && !(*m_lpfnCloseProc)(this))
  804.         return;
  805.  
  806.     // Note: only queries the active document
  807.     CDocument* pDocument = GetActiveDocument();
  808.     if (pDocument != NULL && !pDocument->CanCloseFrame(this))
  809.     {
  810.         // document can't close right now -- don't close it
  811.         return;
  812.     }
  813.     CWinApp* pApp = AfxGetApp();
  814.     if (pApp->m_pMainWnd == this)
  815.     {
  816.         // attempt to save all documents
  817.         if (pDocument == NULL && !pApp->SaveAllModified())
  818.             return;     // don't close it
  819.  
  820.         // hide the application's windows before closing all the documents
  821.         pApp->HideApplication();
  822.  
  823.         // close all documents first
  824.         pApp->CloseAllDocuments(FALSE);
  825.  
  826.         // don't exit if there are outstanding component objects
  827.         if (!AfxOleCanExitApp())
  828.         {
  829.             // take user out of control of the app
  830.             AfxOleSetUserCtrl(FALSE);
  831.  
  832.             // don't destroy the main window and close down just yet
  833.             //  (there are outstanding component (OLE) objects)
  834.             return;
  835.         }
  836.  
  837.         // there are cases where destroying the documents may destroy the
  838.         //  main window of the application.
  839.         if (!afxContextIsDLL && pApp->m_pMainWnd == NULL)
  840.         {
  841.             AfxPostQuitMessage(0);
  842.             return;
  843.         }
  844.     }
  845.  
  846.     // detect the case that this is the last frame on the document and
  847.     // shut down with OnCloseDocument instead.
  848.     if (pDocument != NULL && pDocument->m_bAutoDelete)
  849.     {
  850.         BOOL bOtherFrame = FALSE;
  851.         POSITION pos = pDocument->GetFirstViewPosition();
  852.         while (pos != NULL)
  853.         {
  854.             CView* pView = pDocument->GetNextView(pos);
  855.             ASSERT_VALID(pView);
  856.             if (pView->GetParentFrame() != this)
  857.             {
  858.                 bOtherFrame = TRUE;
  859.                 break;
  860.             }
  861.         }
  862.         if (!bOtherFrame)
  863.         {
  864.             pDocument->OnCloseDocument();
  865.             return;
  866.         }
  867.  
  868.         // allow the document to cleanup before the window is destroyed
  869.         pDocument->PreCloseFrame(this);
  870.     }
  871.  
  872.     // then destroy the window
  873.     DestroyWindow();
  874. }
  875.  
  876. void CFrameWnd::OnDestroy()
  877. {
  878.     DestroyDockBars();
  879.  
  880.     // reset menu to default before final shutdown
  881.     if (m_hMenuDefault != NULL && ::GetMenu(m_hWnd) != m_hMenuDefault)
  882.     {
  883.         ::SetMenu(m_hWnd, m_hMenuDefault);
  884.         ASSERT(::GetMenu(m_hWnd) == m_hMenuDefault);
  885.     }
  886.  
  887.     // Automatically quit when the main window is destroyed.
  888.     if (AfxGetApp()->m_pMainWnd == this)
  889.     {
  890.         // closing the main application window
  891.         ::WinHelp(m_hWnd, NULL, HELP_QUIT, 0L);
  892.  
  893.         // will call PostQuitMessage in CWnd::OnNcDestroy
  894.     }
  895.     CWnd::OnDestroy();
  896. }
  897.  
  898. void CFrameWnd::RemoveControlBar(CControlBar *pBar)
  899. {
  900.     POSITION pos = m_listControlBars.Find(pBar);
  901.     if (pos != NULL)
  902.         m_listControlBars.RemoveAt(pos);
  903. }
  904.  
  905. /////////////////////////////////////////////////////////////////////////////
  906. // CFrameWnd command/message routing
  907.  
  908. BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
  909.     AFX_CMDHANDLERINFO* pHandlerInfo)
  910. {
  911.     // pump through current view FIRST
  912.     CView* pView = GetActiveView();
  913.     if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  914.         return TRUE;
  915.  
  916.     // then pump through frame
  917.     if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  918.         return TRUE;
  919.  
  920.     // last but not least, pump through app
  921.     CWinApp* pApp = AfxGetApp();
  922.     if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  923.         return TRUE;
  924.  
  925.     return FALSE;
  926. }
  927.  
  928. // Delegate scroll messages to active view as well
  929. void CFrameWnd::OnHScroll(UINT, UINT, CScrollBar*)
  930. {
  931.     CWnd* pActiveView = GetActiveView();
  932.     if (pActiveView != NULL)
  933.     {
  934.         const MSG* pMsg = GetCurrentMessage();
  935.         pActiveView->SendMessage(WM_HSCROLL, pMsg->wParam, pMsg->lParam);
  936.     }
  937. }
  938.  
  939. void CFrameWnd::OnVScroll(UINT, UINT, CScrollBar*)
  940. {
  941.     CWnd* pActiveView = GetActiveView();
  942.     if (pActiveView != NULL)
  943.     {
  944.         const MSG* pMsg = GetCurrentMessage();
  945.         pActiveView->SendMessage(WM_VSCROLL, pMsg->wParam, pMsg->lParam);
  946.     }
  947. }
  948.  
  949. LRESULT CFrameWnd::OnActivateTopLevel(WPARAM wParam, LPARAM lParam)
  950. {
  951. #ifdef _MAC
  952.     BOOL bActive = (LOWORD(wParam) != WA_INACTIVE && !HIWORD(wParam));
  953.  
  954.     if(!bActive && afxData.bOleIgnoreSuspend)
  955.     {
  956.         afxData.bOleIgnoreSuspend = FALSE;
  957.         return 0;
  958.     }
  959. #endif
  960.  
  961.     CWnd::OnActivateTopLevel(wParam, lParam);
  962.  
  963.     // exit Shift+F1 help mode on activation changes
  964.     ExitHelpMode();
  965.  
  966. #ifndef _AFX_NO_OLE_SUPPORT
  967.     // allow OnFrameWindowActivate to be sent to in-place items
  968.     if (m_pNotifyHook != NULL)
  969.     {
  970. #ifdef _MAC
  971.         if (::GetWinActiveMode() != WAM_OLEIPCONTAINER)
  972. #endif
  973.         {
  974.             // activate when active and when not minimized
  975.             m_pNotifyHook->OnActivate(
  976.                 LOWORD(wParam) != WA_INACTIVE && !HIWORD(wParam));
  977.         }
  978.  
  979.     }
  980. #endif
  981.  
  982.     // deactivate current active view
  983.     if (AfxGetThread()->m_pMainWnd == this)
  984.     {
  985.         CView* pActiveView = GetActiveView();
  986.         if (pActiveView == NULL)
  987.             pActiveView = GetActiveFrame()->GetActiveView();
  988.         if (pActiveView != NULL)
  989.             pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
  990.     }
  991.     return 0;
  992. }
  993.  
  994. void CFrameWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
  995. {
  996.     CWnd::OnActivate(nState, pWndOther, bMinimized);
  997.  
  998.     // get top level frame unless this is a child window
  999.     // determine if window should be active or not
  1000.     CFrameWnd* pTopLevel = (GetStyle() & WS_CHILD) ? this : GetTopLevelFrame();
  1001.     ASSERT(pTopLevel != NULL);
  1002.     CWnd* pActive = (nState == WA_INACTIVE ? pWndOther : this);
  1003.     BOOL bStayActive =
  1004.         (pTopLevel == pActive ||
  1005.         (pTopLevel == pActive->GetTopLevelFrame() &&
  1006.         (pActive == pTopLevel ||
  1007.             pActive->SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE) != 0)));
  1008.     pTopLevel->m_nFlags &= ~WF_STAYACTIVE;
  1009.     if (bStayActive)
  1010.         pTopLevel->m_nFlags |= WF_STAYACTIVE;
  1011.  
  1012.     // sync floating windows to the new state
  1013.     NotifyFloatingWindows(bStayActive ? FS_ACTIVATE : FS_DEACTIVATE);
  1014.  
  1015.     // get active view (use active frame if no active view)
  1016.     CView* pActiveView = GetActiveView();
  1017.     if (pActiveView == NULL)
  1018.         pActiveView = GetActiveFrame()->GetActiveView();
  1019.  
  1020.     // when frame gets activated, re-activate current view
  1021.     if (pActiveView != NULL)
  1022.     {
  1023.         if (nState != WA_INACTIVE && !bMinimized)
  1024.             pActiveView->OnActivateView(TRUE, pActiveView, pActiveView);
  1025.  
  1026.         // always notify the view of frame activations
  1027.         pActiveView->OnActivateFrame(nState, this);
  1028.     }
  1029. }
  1030.  
  1031. BOOL CFrameWnd::OnNcActivate(BOOL bActive)
  1032. {
  1033.     // stay active if WF_STAYACTIVE bit is on
  1034.     if (m_nFlags & WF_STAYACTIVE)
  1035.         bActive = TRUE;
  1036.  
  1037.     // but do not stay active if the window is disabled
  1038.     if (!IsWindowEnabled())
  1039.         bActive = FALSE;
  1040.  
  1041.     // do not call the base class because it will call Default()
  1042.     //  and we may have changed bActive.
  1043.     return (BOOL)DefWindowProc(WM_NCACTIVATE, bActive, 0L);
  1044. }
  1045.  
  1046. #ifdef _MAC
  1047. void CFrameWnd::OnActivateApp(BOOL bActive, HTASK hTask)
  1048. {
  1049. #ifndef _AFX_NO_OLE_SUPPORT
  1050.     // allow OnFrameWindowActivate to be sent to in-place items
  1051.     if (m_pNotifyHook != NULL && bActive)
  1052.     {
  1053.         if (::GetWinActiveMode() == WAM_OLEIPCONTAINER)
  1054.         {
  1055.             // ok, the container has an activate msg while the server is still
  1056.             // UIVisible.  This implies that the user has ESCaped the IP session.
  1057.             CView* pActiveView = GetActiveView();
  1058.             if (pActiveView == NULL)
  1059.                 pActiveView = GetActiveFrame()->GetActiveView();
  1060.             ASSERT(pActiveView != NULL);
  1061.             pActiveView->PostMessage(WM_KEYDOWN, VK_ESCAPE, 0);
  1062.         }
  1063.         else
  1064.         {
  1065.             m_pNotifyHook->OnActivate(TRUE);
  1066.         }
  1067.     }
  1068. #endif
  1069.  
  1070.     CWnd::OnActivateApp(bActive, hTask);
  1071.  
  1072.     // The Macintosh DefFrameProc hides toolbars, status bars, etc. when
  1073.     // a frame window is deactivated, and shows them again on activation.
  1074.     // If the frame window changes size while it's deactivated (say because
  1075.     // it's on a Radius Pivot monitor that's pivoted) then RecalcLayout is
  1076.     // called while the control bars are hidden. In this case, we need to
  1077.     // recalc the layout again when the window is reactivated and the
  1078.     // controlbars shown again. Note that we must do the recalc *after*
  1079.     // CWnd::OnActivateApp because it's inside that function that DefFrameProc
  1080.     // gets called to re-show the controlbars.
  1081.  
  1082.     if (bActive)
  1083.         RecalcLayout();
  1084. }
  1085. #endif
  1086.  
  1087. void CFrameWnd::OnSysCommand(UINT nID, LONG lParam)
  1088. {
  1089. #ifdef _MAC
  1090.     // the frame window's system menu is mapped to the Apple menu on the
  1091.     // Macintosh, so choosing About MyApp results in a WM_SYSCOMMAND
  1092.     if (nID == ID_APP_ABOUT)
  1093.     {
  1094.         OnCommand(ID_APP_ABOUT, 0);
  1095.         return;
  1096.     }
  1097. #endif
  1098.  
  1099.     CFrameWnd* pFrameWnd = GetTopLevelFrame();
  1100.     ASSERT_VALID(pFrameWnd);
  1101.  
  1102.     // set status bar as appropriate
  1103.     UINT nItemID = (nID & 0xFFF0);
  1104.  
  1105.     // don't interfere with system commands if not in help mode
  1106.     if (pFrameWnd->m_bHelpMode)
  1107.     {
  1108.         switch (nItemID)
  1109.         {
  1110.         case SC_SIZE:
  1111.         case SC_MOVE:
  1112.         case SC_MINIMIZE:
  1113.         case SC_MAXIMIZE:
  1114.         case SC_NEXTWINDOW:
  1115.         case SC_PREVWINDOW:
  1116.         case SC_CLOSE:
  1117.         case SC_RESTORE:
  1118.         case SC_TASKLIST:
  1119.             if (!SendMessage(WM_COMMANDHELP, 0,
  1120.               HID_BASE_COMMAND+ID_COMMAND_FROM_SC(nItemID)))
  1121.                 SendMessage(WM_COMMAND, ID_DEFAULT_HELP);
  1122.             return;
  1123.         }
  1124.     }
  1125.  
  1126.     // call default functionality
  1127.     CWnd::OnSysCommand(nID, lParam);
  1128. }
  1129.  
  1130. /////////////////////////////////////////////////////////////////////////////
  1131. // default frame processing
  1132.  
  1133. // default drop processing will attempt to open the file
  1134. void CFrameWnd::OnDropFiles(HDROP hDropInfo)
  1135. {
  1136.     SetActiveWindow();      // activate us first !
  1137.     UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
  1138.  
  1139.     CWinApp* pApp = AfxGetApp();
  1140.     for (UINT iFile = 0; iFile < nFiles; iFile++)
  1141.     {
  1142.         TCHAR szFileName[_MAX_PATH];
  1143.         ::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
  1144.         pApp->OpenDocumentFile(szFileName);
  1145.     }
  1146.     ::DragFinish(hDropInfo);
  1147. }
  1148.  
  1149. // query end session for main frame will attempt to close it all down
  1150. BOOL CFrameWnd::OnQueryEndSession()
  1151. {
  1152.     CWinApp* pApp = AfxGetApp();
  1153.     if (pApp->m_pMainWnd == this)
  1154.         return pApp->SaveAllModified();
  1155.  
  1156.     return TRUE;
  1157. }
  1158.  
  1159. // when Windows session ends, close all documents
  1160. void CFrameWnd::OnEndSession(BOOL bEnding)
  1161. {
  1162.     CWinApp* pApp = AfxGetApp();
  1163.     ASSERT_VALID(pApp);
  1164.     if (bEnding && pApp->m_pMainWnd == this)
  1165.     {
  1166.         AfxOleSetUserCtrl(TRUE);    // keeps from randomly shutting down
  1167.         pApp->CloseAllDocuments(TRUE);
  1168.  
  1169.         // allow application to save settings, etc.
  1170.         pApp->ExitInstance();
  1171.     }
  1172. }
  1173.  
  1174. #ifndef _MAC
  1175. /////////////////////////////////////////////////////////////////////////////
  1176. // Support for Shell DDE Execute messages
  1177.  
  1178. LRESULT CFrameWnd::OnDDEInitiate(WPARAM wParam, LPARAM lParam)
  1179. {
  1180.     CWinApp* pApp = AfxGetApp();
  1181.     ASSERT_VALID(pApp);
  1182.     if (LOWORD(lParam) != 0 && HIWORD(lParam) != 0 &&
  1183.         (ATOM)LOWORD(lParam) == pApp->m_atomApp &&
  1184.         (ATOM)HIWORD(lParam) == pApp->m_atomSystemTopic)
  1185.     {
  1186.         // make duplicates of the incoming atoms (really adding a reference)
  1187.         TCHAR szAtomName[_MAX_PATH];
  1188.         VERIFY(GlobalGetAtomName(pApp->m_atomApp,
  1189.             szAtomName, _MAX_PATH - 1) != 0);
  1190.         VERIFY(GlobalAddAtom(szAtomName) == pApp->m_atomApp);
  1191.         VERIFY(GlobalGetAtomName(pApp->m_atomSystemTopic,
  1192.             szAtomName, _MAX_PATH - 1) != 0);
  1193.         VERIFY(GlobalAddAtom(szAtomName) == pApp->m_atomSystemTopic);
  1194.  
  1195.         // send the WM_DDE_ACK (caller will delete duplicate atoms)
  1196.         ::SendMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hWnd,
  1197.             MAKELPARAM(pApp->m_atomApp, pApp->m_atomSystemTopic));
  1198.     }
  1199.     return 0L;
  1200. }
  1201.  
  1202. // always ACK the execute command - even if we do nothing
  1203. LRESULT CFrameWnd::OnDDEExecute(WPARAM wParam, LPARAM lParam)
  1204. {
  1205.     // unpack the DDE message
  1206.     UINT unused;
  1207.     HGLOBAL hData;
  1208.     VERIFY(UnpackDDElParam(WM_DDE_EXECUTE, lParam, &unused, (UINT*)&hData));
  1209.  
  1210.     // get the command string
  1211.     TCHAR szCommand[_MAX_PATH * 2];
  1212.     LPCTSTR lpsz = (LPCTSTR)GlobalLock(hData);
  1213.     lstrcpyn(szCommand, lpsz, _countof(szCommand));
  1214.     GlobalUnlock(hData);
  1215.  
  1216.     // acknowledge now - before attempting to execute
  1217.     ::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hWnd,
  1218.         ReuseDDElParam(lParam, WM_DDE_EXECUTE, WM_DDE_ACK,
  1219.         (UINT)0x8000, (UINT)hData));
  1220.  
  1221.     // don't execute the command when the window is disabled
  1222.     if (!IsWindowEnabled())
  1223.     {
  1224.         TRACE1("Warning: DDE command '%s' ignored because window is disabled.\n",
  1225.             szCommand);
  1226.         return 0;
  1227.     }
  1228.  
  1229.     // execute the command
  1230.     if (!AfxGetApp()->OnDDECommand(szCommand))
  1231.         TRACE1("Error: failed to execute DDE command '%s'.\n", szCommand);
  1232.  
  1233.     return 0L;
  1234. }
  1235.  
  1236. LRESULT CFrameWnd::OnDDETerminate(WPARAM wParam, LPARAM lParam)
  1237. {
  1238.     ::PostMessage((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)m_hWnd, lParam);
  1239.     return 0L;
  1240. }
  1241. #endif  //!_MAC
  1242.  
  1243. /////////////////////////////////////////////////////////////////////////////
  1244. // CFrameWnd attributes
  1245.  
  1246. CView* CFrameWnd::GetActiveView() const
  1247. {
  1248.     ASSERT(m_pViewActive == NULL ||
  1249.         m_pViewActive->IsKindOf(RUNTIME_CLASS(CView)));
  1250.     return m_pViewActive;
  1251. }
  1252.  
  1253. void CFrameWnd::SetActiveView(CView* pViewNew, BOOL bNotify)
  1254. {
  1255. #ifdef _DEBUG
  1256.     if (pViewNew != NULL)
  1257.     {
  1258.         ASSERT(IsChild(pViewNew));
  1259.         ASSERT_KINDOF(CView, pViewNew);
  1260.     }
  1261. #endif //_DEBUG
  1262.  
  1263.     CView* pViewOld = m_pViewActive;
  1264.     if (pViewNew == pViewOld)
  1265.         return;     // do not re-activate if SetActiveView called more than once
  1266.  
  1267.     m_pViewActive = NULL;   // no active for the following processing
  1268.  
  1269.     // deactivate the old one
  1270.     if (pViewOld != NULL)
  1271.         pViewOld->OnActivateView(FALSE, pViewNew, pViewOld);
  1272.  
  1273.     // if the OnActivateView moves the active window,
  1274.     //    that will veto this change
  1275.     if (m_pViewActive != NULL)
  1276.         return;     // already set
  1277.     m_pViewActive = pViewNew;
  1278.  
  1279.     // activate
  1280.     if (pViewNew != NULL && bNotify)
  1281.         pViewNew->OnActivateView(TRUE, pViewNew, pViewOld);
  1282. }
  1283.  
  1284. /////////////////////////////////////////////////////////////////////////////
  1285. // Special view swapping/activation
  1286.  
  1287. void CFrameWnd::OnSetFocus(CWnd* pOldWnd)
  1288. {
  1289.     if (m_pViewActive != NULL)
  1290.         m_pViewActive->SetFocus();
  1291.     else
  1292.         CWnd::OnSetFocus(pOldWnd);
  1293. }
  1294.  
  1295. CDocument* CFrameWnd::GetActiveDocument()
  1296. {
  1297.     ASSERT_VALID(this);
  1298.     CView* pView = GetActiveView();
  1299.     if (pView != NULL)
  1300.         return pView->GetDocument();
  1301.     return NULL;
  1302. }
  1303.  
  1304. void CFrameWnd::ShowControlBar(CControlBar* pBar, BOOL bShow, BOOL bDelay)
  1305. {
  1306.     ASSERT(pBar != NULL);
  1307.     CFrameWnd* pParentFrame = pBar->GetDockingFrame();
  1308.     ASSERT(pParentFrame->GetTopLevelParent() == GetTopLevelParent());
  1309.         // parent frame of bar must be related
  1310.  
  1311.     if (bDelay)
  1312.     {
  1313.         pBar->DelayShow(bShow);
  1314.         pParentFrame->DelayRecalcLayout();
  1315.     }
  1316.     else
  1317.     {
  1318.         pBar->SetWindowPos(NULL, 0, 0, 0, 0,
  1319.             SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|
  1320.             (bShow ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
  1321.         // call DelayShow to clear any contradictory DelayShow
  1322.         pBar->DelayShow(bShow);
  1323.         if (bShow || !pBar->IsFloating())
  1324.             pParentFrame->RecalcLayout(FALSE);
  1325.     }
  1326.  
  1327.     // show or hide the floating frame as appropriate
  1328.     if (pBar->IsFloating())
  1329.     {
  1330.         int nVisCount = pBar->m_pDockBar != NULL ?
  1331.             pBar->m_pDockBar->GetDockedVisibleCount() : bShow != FALSE;
  1332.         if (nVisCount == 1 && bShow)
  1333.         {
  1334.             pParentFrame->m_nShowDelay = -1;
  1335.             if (bDelay)
  1336.             {
  1337.                 pParentFrame->m_nShowDelay = SW_SHOWNA;
  1338.                 pParentFrame->RecalcLayout(FALSE);
  1339.             }
  1340.             else
  1341.                 pParentFrame->ShowWindow(SW_SHOWNA);
  1342.         }
  1343.         else if (nVisCount == 0)
  1344.         {
  1345.             ASSERT(!bShow);
  1346.             pParentFrame->m_nShowDelay = -1;
  1347.             if (bDelay)
  1348.                 pParentFrame->m_nShowDelay = SW_HIDE;
  1349.             else
  1350.                 pParentFrame->ShowWindow(SW_HIDE);
  1351.         }
  1352.         else if (!bDelay)
  1353.         {
  1354.             pParentFrame->RecalcLayout(FALSE);
  1355.         }
  1356.     }
  1357. }
  1358.  
  1359. /////////////////////////////////////////////////////////////////////////////
  1360. // Command prompts
  1361.  
  1362. void CFrameWnd::OnInitMenuPopup(CMenu* pMenu, UINT, BOOL bSysMenu)
  1363. {
  1364.     AfxCancelModes(m_hWnd);
  1365.  
  1366.     if (bSysMenu)
  1367.         return;     // don't support system menu
  1368.  
  1369.     ASSERT(pMenu != NULL);
  1370.     // check the enabled state of various menu items
  1371.  
  1372.     CCmdUI state;
  1373.     state.m_pMenu = pMenu;
  1374.     ASSERT(state.m_pOther == NULL);
  1375.     ASSERT(state.m_pParentMenu == NULL);
  1376.  
  1377.     // determine if menu is popup in top-level menu and set m_pOther to
  1378.     //  it if so (m_pParentMenu == NULL indicates that it is secondary popup)
  1379.     HMENU hParentMenu;
  1380.     if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu)
  1381.         state.m_pParentMenu = pMenu;    // parent == child for tracking popup
  1382.     else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
  1383.     {
  1384.         CWnd* pParent = GetTopLevelParent();
  1385.             // child windows don't have menus -- need to go to the top!
  1386.         if (pParent != NULL &&
  1387.             (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
  1388.         {
  1389.             int nIndexMax = ::GetMenuItemCount(hParentMenu);
  1390.             for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
  1391.             {
  1392.                 if (::GetSubMenu(hParentMenu, nIndex) == pMenu->m_hMenu)
  1393.                 {
  1394.                     // when popup is found, m_pParentMenu is containing menu
  1395.                     state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
  1396.                     break;
  1397.                 }
  1398.             }
  1399.         }
  1400.     }
  1401.  
  1402.     state.m_nIndexMax = pMenu->GetMenuItemCount();
  1403.     for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
  1404.       state.m_nIndex++)
  1405.     {
  1406.         state.m_nID = pMenu->GetMenuItemID(state.m_nIndex);
  1407.         if (state.m_nID == 0)
  1408.             continue; // menu separator or invalid cmd - ignore it
  1409.  
  1410.         ASSERT(state.m_pOther == NULL);
  1411.         ASSERT(state.m_pMenu != NULL);
  1412.         if (state.m_nID == (UINT)-1)
  1413.         {
  1414.             // possibly a popup menu, route to first item of that popup
  1415.             state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex);
  1416.             if (state.m_pSubMenu == NULL ||
  1417.                 (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
  1418.                 state.m_nID == (UINT)-1)
  1419.             {
  1420.                 continue;       // first item of popup can't be routed to
  1421.             }
  1422.             state.DoUpdate(this, FALSE);    // popups are never auto disabled
  1423.         }
  1424.         else
  1425.         {
  1426.             // normal menu item
  1427.             // Auto enable/disable if frame window has 'm_bAutoMenuEnable'
  1428.             //    set and command is _not_ a system command.
  1429.             state.m_pSubMenu = NULL;
  1430.             state.DoUpdate(this, m_bAutoMenuEnable && state.m_nID < 0xF000);
  1431.         }
  1432.  
  1433.         // adjust for menu deletions and additions
  1434.         UINT nCount = pMenu->GetMenuItemCount();
  1435.         if (nCount < state.m_nIndexMax)
  1436.         {
  1437.             state.m_nIndex -= (state.m_nIndexMax - nCount);
  1438.             while (state.m_nIndex < nCount &&
  1439.                 pMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
  1440.             {
  1441.                 state.m_nIndex++;
  1442.             }
  1443.         }
  1444.         state.m_nIndexMax = nCount;
  1445.     }
  1446. }
  1447.  
  1448. void CFrameWnd::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU /*hSysMenu*/)
  1449. {
  1450.     CFrameWnd* pFrameWnd = GetTopLevelFrame();
  1451.     ASSERT_VALID(pFrameWnd);
  1452.  
  1453.     // set the tracking state (update on idle)
  1454.     if (nFlags == 0xFFFF)
  1455.     {
  1456.         // cancel menu operation (go back to idle now)
  1457.         m_nFlags &= ~WF_NOPOPMSG;
  1458.         if (!pFrameWnd->m_bHelpMode)
  1459.             m_nIDTracking = AFX_IDS_IDLEMESSAGE;
  1460.         else
  1461.             m_nIDTracking = AFX_IDS_HELPMODEMESSAGE;
  1462.         SendMessage(WM_SETMESSAGESTRING, (WPARAM)m_nIDTracking);
  1463.         ASSERT(m_nIDTracking == m_nIDLastMessage);
  1464.  
  1465.         // update right away
  1466.         CWnd* pWnd = GetMessageBar();
  1467.         if (pWnd != NULL)
  1468.             pWnd->UpdateWindow();
  1469.     }
  1470.     else
  1471.     {
  1472.         if (nItemID == 0 || nFlags & (MF_SEPARATOR|MF_POPUP))
  1473.         {
  1474.             // nothing should be displayed
  1475.             m_nIDTracking = 0;
  1476.         }
  1477. #ifdef _MAC
  1478.         else if (nItemID == SC_DESKACCESSORY)
  1479.         {
  1480.             m_nIDTracking = AFX_IDS_DESKACCESSORY;
  1481.         }
  1482. #endif
  1483.         else if (nItemID >= 0xF000 && nItemID < 0xF1F0) // max of 31 SC_s
  1484.         {
  1485.             // special strings table entries for system commands
  1486.             m_nIDTracking = ID_COMMAND_FROM_SC(nItemID);
  1487.             ASSERT(m_nIDTracking >= AFX_IDS_SCFIRST &&
  1488.                 m_nIDTracking < AFX_IDS_SCFIRST + 31);
  1489.         }
  1490.         else if (nItemID >= AFX_IDM_FIRST_MDICHILD)
  1491.         {
  1492.             // all MDI Child windows map to the same help id
  1493.             m_nIDTracking = AFX_IDS_MDICHILD;
  1494.         }
  1495.         else
  1496.         {
  1497.             // track on idle
  1498.             m_nIDTracking = nItemID;
  1499.         }
  1500.         pFrameWnd->m_nFlags |= WF_NOPOPMSG;
  1501.     }
  1502.  
  1503.     // when running in-place, it is necessary to cause a message to
  1504.     //  be pumped through the queue.
  1505.     if (m_nIDTracking != m_nIDLastMessage && GetParent() != NULL)
  1506.         PostMessage(WM_KICKIDLE);
  1507. }
  1508.  
  1509. void CFrameWnd::GetMessageString(UINT nID, CString& rMessage) const
  1510. {
  1511.     // load appropriate string
  1512.     LPTSTR lpsz = rMessage.GetBuffer(255);
  1513.     if (AfxLoadString(nID, lpsz) != 0)
  1514.     {
  1515.         // first newline terminates actual string
  1516.         lpsz = _tcschr(lpsz, '\n');
  1517.         if (lpsz != NULL)
  1518.             *lpsz = '\0';
  1519.     }
  1520.     else
  1521.     {
  1522.         // not found
  1523.         TRACE1("Warning: no message line prompt for ID 0x%04X.\n", nID);
  1524.     }
  1525.     rMessage.ReleaseBuffer();
  1526. }
  1527.  
  1528. LRESULT CFrameWnd::OnPopMessageString(WPARAM wParam, LPARAM lParam)
  1529. {
  1530.     if (m_nFlags & WF_NOPOPMSG)
  1531.         return 0;
  1532.  
  1533.     return SendMessage(WM_SETMESSAGESTRING, wParam, lParam);
  1534. }
  1535.  
  1536. LRESULT CFrameWnd::OnSetMessageString(WPARAM wParam, LPARAM lParam)
  1537. {
  1538.     UINT nIDLast = m_nIDLastMessage;
  1539.     m_nFlags &= ~WF_NOPOPMSG;
  1540.  
  1541.     CWnd* pMessageBar = GetMessageBar();
  1542.     if (pMessageBar != NULL)
  1543.     {
  1544.         LPCTSTR lpsz = NULL;
  1545.         CString strMessage;
  1546.  
  1547.         // set the message bar text
  1548.         if (lParam != 0)
  1549.         {
  1550.             ASSERT(wParam == 0);    // can't have both an ID and a string
  1551.             lpsz = (LPCTSTR)lParam; // set an explicit string
  1552.         }
  1553.         else if (wParam != 0)
  1554.         {
  1555.             // map SC_CLOSE to PREVIEW_CLOSE when in print preview mode
  1556.             if (wParam == AFX_IDS_SCCLOSE && m_lpfnCloseProc != NULL)
  1557.                 wParam = AFX_IDS_PREVIEW_CLOSE;
  1558.  
  1559.             // get message associated with the ID indicated by wParam
  1560.             GetMessageString(wParam, strMessage);
  1561.             lpsz = strMessage;
  1562.         }
  1563.         pMessageBar->SetWindowText(lpsz);
  1564.  
  1565.         // update owner of the bar in terms of last message selected
  1566.         CFrameWnd* pFrameWnd = pMessageBar->GetParentFrame();
  1567.         if (pFrameWnd != NULL)
  1568.         {
  1569.             pFrameWnd->m_nIDLastMessage = (UINT)wParam;
  1570.             pFrameWnd->m_nIDTracking = (UINT)wParam;
  1571.         }
  1572.     }
  1573.  
  1574.     m_nIDLastMessage = (UINT)wParam;    // new ID (or 0)
  1575.     m_nIDTracking = (UINT)wParam;       // so F1 on toolbar buttons work
  1576.     return nIDLast;
  1577. }
  1578.  
  1579. CWnd* CFrameWnd::GetMessageBar()
  1580. {
  1581.     return GetDescendantWindow(AFX_IDW_STATUS_BAR, TRUE);
  1582. }
  1583.  
  1584. void CFrameWnd::OnEnterIdle(UINT nWhy, CWnd* pWho)
  1585. {
  1586.     CWnd::OnEnterIdle(nWhy, pWho);
  1587.  
  1588.     if (nWhy != MSGF_MENU || m_nIDTracking == m_nIDLastMessage)
  1589.         return;
  1590.  
  1591.     SetMessageText(m_nIDTracking);
  1592.     ASSERT(m_nIDTracking == m_nIDLastMessage);
  1593. }
  1594.  
  1595. void CFrameWnd::SetMessageText(LPCTSTR lpszText)
  1596. {
  1597.     SendMessage(WM_SETMESSAGESTRING, 0, (LPARAM)lpszText);
  1598. }
  1599.  
  1600. void CFrameWnd::SetMessageText(UINT nID)
  1601. {
  1602.     SendMessage(WM_SETMESSAGESTRING, (WPARAM)nID);
  1603. }
  1604.  
  1605. /////////////////////////////////////////////////////////////////////////////
  1606. // CFrameWnd standard control bar management
  1607.  
  1608. void CFrameWnd::DestroyDockBars()
  1609. {
  1610.     // create a list of all the dock bars
  1611.     // this is necessary because m_listControlBars will change
  1612.     // as the dock bars and floating frames are destroyed
  1613.     CPtrList listDockBars;
  1614.     POSITION pos = m_listControlBars.GetHeadPosition();
  1615.     while (pos != NULL)
  1616.     {
  1617.         CDockBar* pDockBar = (CDockBar*)m_listControlBars.GetNext(pos);
  1618.         ASSERT(pDockBar != NULL);
  1619.         if (pDockBar->IsDockBar())
  1620.             listDockBars.AddTail(pDockBar);
  1621.     }
  1622.     pos = listDockBars.GetHeadPosition();
  1623.     while (pos != NULL)
  1624.     {
  1625.         CDockBar* pDockBar = (CDockBar*)listDockBars.GetNext(pos);
  1626.         if (pDockBar->m_bFloating)
  1627.         {
  1628.             CFrameWnd* pFrameWnd = pDockBar->GetParentFrame();
  1629.             ASSERT_VALID(pFrameWnd);
  1630.             pFrameWnd->DestroyWindow();
  1631.         }
  1632.         else
  1633.             pDockBar->DestroyWindow();
  1634.     }
  1635. }
  1636.  
  1637. CControlBar* CFrameWnd::GetControlBar(UINT nID)
  1638. {
  1639.     if (nID == 0)
  1640.         return NULL;
  1641.     POSITION pos = m_listControlBars.GetHeadPosition();
  1642.     while (pos != NULL)
  1643.     {
  1644.         CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
  1645.         ASSERT(pBar != NULL);
  1646.         if (_AfxGetDlgCtrlID(pBar->m_hWnd) == nID)
  1647.         {
  1648.             ASSERT_KINDOF(CControlBar, pBar);
  1649.             return pBar;
  1650.         }
  1651.     }
  1652.     return NULL;
  1653. }
  1654.  
  1655. void CFrameWnd::OnUpdateControlBarMenu(CCmdUI* pCmdUI)
  1656. {
  1657.     ASSERT(ID_VIEW_STATUS_BAR == AFX_IDW_STATUS_BAR);
  1658.     ASSERT(ID_VIEW_TOOLBAR == AFX_IDW_TOOLBAR);
  1659.  
  1660.     CControlBar* pBar = GetControlBar(pCmdUI->m_nID);
  1661.     if (pBar != NULL)
  1662.     {
  1663.         pCmdUI->SetCheck((pBar->GetStyle() & WS_VISIBLE) != 0);
  1664.         return;
  1665.     }
  1666.     pCmdUI->ContinueRouting();
  1667. }
  1668.  
  1669. BOOL CFrameWnd::OnBarCheck(UINT nID)
  1670. {
  1671.     ASSERT(ID_VIEW_STATUS_BAR == AFX_IDW_STATUS_BAR);
  1672.     ASSERT(ID_VIEW_TOOLBAR == AFX_IDW_TOOLBAR);
  1673.  
  1674.     CControlBar* pBar = GetControlBar(nID);
  1675.     if (pBar != NULL)
  1676.     {
  1677.         ShowControlBar(pBar, (pBar->GetStyle() & WS_VISIBLE) == 0, FALSE);
  1678.         return TRUE;
  1679.     }
  1680.     return FALSE;
  1681. }
  1682.  
  1683. BOOL CFrameWnd::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult)
  1684. {
  1685.     ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
  1686.  
  1687.     // allow top level routing frame to handle the message
  1688.     if (GetRoutingFrame() != NULL)
  1689.         return FALSE;
  1690.  
  1691.     // need to handle both ANSI and UNICODE versions of the message
  1692.     TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
  1693.     TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
  1694.     TCHAR szFullText[256];
  1695.     CString strTipText;
  1696.     UINT nID = pNMHDR->idFrom;
  1697.     if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
  1698.         pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
  1699.     {
  1700.         // idFrom is actually the HWND of the tool
  1701.         nID = _AfxGetDlgCtrlID((HWND)nID);
  1702.     }
  1703.  
  1704.     if (nID != 0) // will be zero on a separator
  1705.     {
  1706.         AfxLoadString(nID, szFullText);
  1707.             // this is the command id, not the button index
  1708.         AfxExtractSubString(strTipText, szFullText, 1, '\n');
  1709.     }
  1710. #ifndef _UNICODE
  1711.     if (pNMHDR->code == TTN_NEEDTEXTA)
  1712.         lstrcpyn(pTTTA->szText, strTipText, _countof(pTTTA->szText));
  1713.     else
  1714.         _mbstowcsz(pTTTW->szText, strTipText, _countof(pTTTW->szText));
  1715. #else
  1716.     if (pNMHDR->code == TTN_NEEDTEXTA)
  1717.         _wcstombsz(pTTTA->szText, strTipText, _countof(pTTTA->szText));
  1718.     else
  1719.         lstrcpyn(pTTTW->szText, strTipText, _countof(pTTTW->szText));
  1720. #endif
  1721.     *pResult = 0;
  1722.  
  1723.     // bring the tooltip window above other popup windows
  1724.     ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
  1725.         SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
  1726.  
  1727.     return TRUE;    // message was handled
  1728. }
  1729.  
  1730. /////////////////////////////////////////////////////////////////////////////
  1731. // Support for standard status bar
  1732.  
  1733. void CFrameWnd::OnUpdateKeyIndicator(CCmdUI* pCmdUI)
  1734. {
  1735.     UINT nVK;
  1736.     UINT flag = 0x0001;
  1737.  
  1738.     switch (pCmdUI->m_nID)
  1739.     {
  1740.     case ID_INDICATOR_CAPS:
  1741.         nVK = VK_CAPITAL;
  1742.         break;
  1743.  
  1744.     case ID_INDICATOR_NUM:
  1745.         nVK = VK_NUMLOCK;
  1746.         break;
  1747.  
  1748.     case ID_INDICATOR_SCRL:
  1749.         nVK = VK_SCROLL;
  1750.         break;
  1751.  
  1752.     case ID_INDICATOR_KANA:
  1753.         nVK = VK_KANA;
  1754.         // WINBUG: Special case for Windows 3.x.  The wrong bit was toggled
  1755.         // in those systems so this must be special cased.  This is fixed
  1756.         // on systems whose version is 4.x or greater.
  1757.         if (!afxData.bWin4)
  1758.             flag = 0x8000;
  1759.         break;
  1760.  
  1761.     default:
  1762.         TRACE1("Warning: OnUpdateKeyIndicator - unknown indicator 0x%04X.\n",
  1763.             pCmdUI->m_nID);
  1764.         pCmdUI->ContinueRouting();
  1765.         return; // not for us
  1766.     }
  1767.  
  1768.     pCmdUI->Enable(::GetKeyState(nVK) & flag);
  1769.         // enable static text based on toggled key state
  1770.     ASSERT(pCmdUI->m_bEnableChanged);
  1771. }
  1772.  
  1773. void CFrameWnd::OnUpdateContextHelp(CCmdUI* pCmdUI)
  1774. {
  1775.     if (AfxGetMainWnd() == this)
  1776.         pCmdUI->SetCheck(!!m_bHelpMode);
  1777.     else
  1778.         pCmdUI->ContinueRouting();
  1779. }
  1780.  
  1781. /////////////////////////////////////////////////////////////////////////////
  1782. // Setting title of frame window - UISG standard
  1783.  
  1784. void CFrameWnd::OnUpdateFrameTitle(BOOL bAddToTitle)
  1785. {
  1786.     if ((GetStyle() & FWS_ADDTOTITLE) == 0)
  1787.         return;     // leave it alone!
  1788.  
  1789. #ifndef _AFX_NO_OLE_SUPPORT
  1790.     // allow hook to set the title (used for OLE support)
  1791.     if (m_pNotifyHook != NULL && m_pNotifyHook->OnUpdateFrameTitle())
  1792.         return;
  1793. #endif
  1794.  
  1795.     CDocument* pDocument = GetActiveDocument();
  1796.     if (bAddToTitle && pDocument != NULL)
  1797.         UpdateFrameTitleForDocument(pDocument->GetTitle());
  1798.     else
  1799.         UpdateFrameTitleForDocument(NULL);
  1800. }
  1801.  
  1802. void CFrameWnd::UpdateFrameTitleForDocument(LPCTSTR lpszDocName)
  1803. {
  1804.     // copy first part of title loaded at time of frame creation
  1805.     TCHAR szText[256+_MAX_PATH];
  1806.  
  1807.     if (GetStyle() & FWS_PREFIXTITLE)
  1808.     {
  1809.         szText[0] = '\0';   // start with nothing
  1810.  
  1811.         // get name of currently active view
  1812.         if (lpszDocName != NULL)
  1813.         {
  1814.             lstrcpy(szText, lpszDocName);
  1815.             // add current window # if needed
  1816.             if (m_nWindow > 0)
  1817.                 wsprintf(szText + lstrlen(szText), _T(":%d"), m_nWindow);
  1818.             lstrcat(szText, _T(" - "));
  1819.         }
  1820.         lstrcat(szText, m_strTitle);
  1821.     }
  1822.     else
  1823.     {
  1824.         // get name of currently active view
  1825.         lstrcpy(szText, m_strTitle);
  1826.         if (lpszDocName != NULL)
  1827.         {
  1828.             lstrcat(szText, _T(" - "));
  1829.             lstrcat(szText, lpszDocName);
  1830.             // add current window # if needed
  1831.             if (m_nWindow > 0)
  1832.                 wsprintf(szText + lstrlen(szText), _T(":%d"), m_nWindow);
  1833.         }
  1834.     }
  1835.  
  1836.     // set title if changed, but don't remove completely
  1837.     // Note: will be excessive for MDI Frame with maximized child
  1838.     AfxSetWindowText(m_hWnd, szText);
  1839. }
  1840.  
  1841. /////////////////////////////////////////////////////////////////////////////
  1842.  
  1843. void CFrameWnd::OnSetPreviewMode(BOOL bPreview, CPrintPreviewState* pState)
  1844. {
  1845.     // default implementation changes control bars, menu and main pane window
  1846.  
  1847. #ifndef _AFX_NO_OLE_SUPPORT
  1848.     CFrameWnd* pActiveFrame = GetActiveFrame();
  1849.     ASSERT_VALID(pActiveFrame);
  1850.     if (bPreview && pActiveFrame->m_pNotifyHook != NULL)
  1851.         pActiveFrame->m_pNotifyHook->OnDocActivate(FALSE);
  1852. #endif
  1853.  
  1854.     // Set visibility of standard ControlBars (only the first 32)
  1855.     DWORD dwOldStates = 0;
  1856.     POSITION pos = m_listControlBars.GetHeadPosition();
  1857.     while (pos != NULL)
  1858.     {
  1859.         CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
  1860.         ASSERT_VALID(pBar);
  1861.         UINT nID = _AfxGetDlgCtrlID(pBar->m_hWnd);
  1862.         if (nID >= AFX_IDW_CONTROLBAR_FIRST && nID <= AFX_IDW_CONTROLBAR_FIRST+31)
  1863.         {
  1864.             DWORD dwMask = 1L << (nID - AFX_IDW_CONTROLBAR_FIRST);
  1865.             if (pBar->IsVisible())
  1866.                 dwOldStates |= dwMask;      // save if previously visible
  1867.             if (!pBar->IsDockBar() || nID != AFX_IDW_DOCKBAR_FLOAT)
  1868.                 ShowControlBar(pBar, (pState->dwStates & dwMask), TRUE);
  1869.         }
  1870.     }
  1871.     pState->dwStates = dwOldStates; // save for restore
  1872.  
  1873.     if (bPreview)
  1874.     {
  1875.         // Entering Print Preview
  1876.         ASSERT(m_lpfnCloseProc == NULL);    // no chaining
  1877.         m_lpfnCloseProc = pState->lpfnCloseProc;
  1878.  
  1879.         // show any modeless dialogs, popup windows, float tools, etc
  1880.         ShowOwnedWindows(FALSE);
  1881.  
  1882.         // Hide the main pane
  1883.         HWND hWnd = ::GetDlgItem(m_hWnd, pState->nIDMainPane);
  1884.         ASSERT(hWnd != NULL);       // must be one that we are hiding!
  1885.         ::ShowWindow(hWnd, SW_HIDE);
  1886.  
  1887.         // Get rid of the menu first (will resize the window)
  1888.         pState->hMenu = ::GetMenu(m_hWnd);
  1889.         if (pState->hMenu != NULL)
  1890.         {
  1891.             // Invalidate before SetMenu since we are going to replace
  1892.             //  the frame's client area anyway
  1893.             Invalidate();
  1894.             SetMenu(NULL);
  1895.             m_nIdleFlags &= ~idleMenu;  // avoid any idle menu processing
  1896.         }
  1897.  
  1898.         // Save the accelerator table and remove it.
  1899.         pState->hAccelTable = m_hAccelTable;
  1900.         m_hAccelTable = NULL;
  1901.         LoadAccelTable(MAKEINTRESOURCE(AFX_IDR_PREVIEW_ACCEL));
  1902.  
  1903.         // Make room for the PreviewView by changing AFX_IDW_PANE_FIRST's ID
  1904.         //  to AFX_IDW_PREVIEW_FIRST
  1905.         if (pState->nIDMainPane != AFX_IDW_PANE_FIRST)
  1906.             hWnd = ::GetDlgItem(m_hWnd, AFX_IDW_PANE_FIRST);
  1907.         if (hWnd != NULL)
  1908.             _AfxSetDlgCtrlID(hWnd, AFX_IDW_PANE_SAVE);
  1909.  
  1910. #ifdef _DEBUG
  1911.         if ((::GetWindowLong(m_hWnd, GWL_STYLE) & (WS_HSCROLL|WS_VSCROLL)) != 0)
  1912.             TRACE0("Warning: scroll bars in frame windows may cause unusual behaviour.\n");
  1913. #endif
  1914.     }
  1915.     else
  1916.     {
  1917.         // Leaving Preview
  1918.         m_lpfnCloseProc = NULL;
  1919.  
  1920.         // shift original AFX_IDW_PANE_FIRST back to its rightful ID
  1921.         HWND hWnd = ::GetDlgItem(m_hWnd, AFX_IDW_PANE_SAVE);
  1922.         if (hWnd != NULL)
  1923.         {
  1924.             HWND hWndTemp = ::GetDlgItem(m_hWnd, AFX_IDW_PANE_FIRST);
  1925.             if (hWndTemp != NULL)
  1926.                 _AfxSetDlgCtrlID(hWndTemp, AFX_IDW_PANE_SAVE);
  1927.             _AfxSetDlgCtrlID(hWnd, AFX_IDW_PANE_FIRST);
  1928.         }
  1929.  
  1930.         // put the menu back in place if it was removed before
  1931.         if (pState->hMenu != NULL)
  1932.         {
  1933.             // Invalidate before SetMenu since we are going to replace
  1934.             //  the frame's client area anyway
  1935.             Invalidate();
  1936.             ::SetMenu(m_hWnd, pState->hMenu);
  1937.         }
  1938.  
  1939.         // recalc layout now, before showing the main pane
  1940. #ifndef _AFX_NO_OLE_SUPPORT
  1941.         if (pActiveFrame->m_pNotifyHook != NULL)
  1942.             pActiveFrame->m_pNotifyHook->OnDocActivate(TRUE);
  1943. #endif
  1944.         RecalcLayout();
  1945.  
  1946.         // now show main pane that was hidden
  1947.         if (pState->nIDMainPane != AFX_IDW_PANE_FIRST)
  1948.             hWnd = ::GetDlgItem(m_hWnd, pState->nIDMainPane);
  1949.         ASSERT(hWnd != NULL);
  1950.         ::ShowWindow(hWnd, SW_SHOW);
  1951.  
  1952.         // Restore the Accelerator table
  1953.         m_hAccelTable = pState->hAccelTable;
  1954.  
  1955.         // show any modeless dialogs, popup windows, float tools, etc
  1956.         ShowOwnedWindows(TRUE);
  1957.     }
  1958. }
  1959.  
  1960. void CFrameWnd::DelayUpdateFrameMenu(HMENU hMenuAlt)
  1961. {
  1962.     m_hMenuAlt = hMenuAlt;
  1963.     m_nIdleFlags |= idleMenu;
  1964. }
  1965.  
  1966. void CFrameWnd::OnIdleUpdateCmdUI()
  1967. {
  1968.     // update menu if necessary
  1969.     if (m_nIdleFlags & idleMenu)
  1970.         OnUpdateFrameMenu(m_hMenuAlt);
  1971.  
  1972.     // update title if necessary
  1973.     if (m_nIdleFlags & idleTitle)
  1974.         OnUpdateFrameTitle(TRUE);
  1975.  
  1976.     // recalc layout if necessary
  1977.     if (m_nIdleFlags & idleLayout)
  1978.     {
  1979.         RecalcLayout(m_nIdleFlags & idleNotify);
  1980.         UpdateWindow();
  1981.     }
  1982.  
  1983.     // set the current message string if necessary
  1984.     if (m_nIDTracking != m_nIDLastMessage)
  1985.     {
  1986.         SetMessageText(m_nIDTracking);
  1987.         ASSERT(m_nIDTracking == m_nIDLastMessage);
  1988.     }
  1989.     m_nIdleFlags = 0;
  1990. }
  1991.  
  1992. CFrameWnd* CFrameWnd::GetActiveFrame()
  1993. {
  1994.     // by default, the active frame is the frame itself (MDI is different)
  1995.     return this;
  1996. }
  1997.  
  1998. void CFrameWnd::RecalcLayout(BOOL bNotify)
  1999. {
  2000.     if (m_bInRecalcLayout)
  2001.         return;
  2002.  
  2003.     m_bInRecalcLayout = TRUE;
  2004.     // clear idle flags for recalc layout if called elsewhere
  2005.     if (m_nIdleFlags & idleNotify)
  2006.         bNotify = TRUE;
  2007.     m_nIdleFlags &= ~(idleLayout|idleNotify);
  2008.  
  2009. #ifndef _AFX_NO_OLE_SUPPORT
  2010.     // call the layout hook -- OLE support uses this hook
  2011.     if (bNotify && m_pNotifyHook != NULL)
  2012.         m_pNotifyHook->OnRecalcLayout();
  2013. #endif
  2014.  
  2015.     // reposition all the child windows (regardless of ID)
  2016.     if (GetStyle() & FWS_SNAPTOBARS)
  2017.     {
  2018.         CRect rect(0, 0, 32767, 32767);
  2019.         RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,
  2020.             &rect, &rect, FALSE);
  2021.         RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra,
  2022.             &m_rectBorder, &rect, TRUE);
  2023.         CalcWindowRect(&rect);
  2024.         SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),
  2025.             SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  2026.     }
  2027.     else
  2028.         RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra, &m_rectBorder);
  2029.     m_bInRecalcLayout = FALSE;
  2030. }
  2031.  
  2032. // CFrameWnd implementation of OLE border space negotiation
  2033. BOOL CFrameWnd::NegotiateBorderSpace(UINT nBorderCmd, LPRECT lpRectBorder)
  2034. {
  2035.     CRect border, request;
  2036.  
  2037.     switch (nBorderCmd)
  2038.     {
  2039.     case borderGet:
  2040.         ASSERT(lpRectBorder != NULL);
  2041. #ifdef _MAC
  2042.         if (m_pViewActive->GetParentFrame() == GetTopLevelFrame())
  2043.         {
  2044.             // SDI
  2045.             ASSERT((GetExStyle() & WS_EX_MDIFRAME) == 0);
  2046.  
  2047.             lpRectBorder->left = 0;
  2048.             lpRectBorder->top = GetSystemMetrics(SM_CYMENU);
  2049.             lpRectBorder->right = GetSystemMetrics(SM_CXSCREEN) - 1;
  2050.             lpRectBorder->bottom = GetSystemMetrics(SM_CYSCREEN) - 1 + GetSystemMetrics(SM_CYMENU);
  2051.             ScreenToClient((POINT*)lpRectBorder);
  2052.             ScreenToClient((POINT*)lpRectBorder + 1);
  2053.             return TRUE;
  2054.         }
  2055. #endif
  2056.         RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,
  2057.             lpRectBorder);
  2058.         break;
  2059.  
  2060.     case borderRequest:
  2061.         return TRUE;
  2062.  
  2063.     case borderSet:
  2064.         if (lpRectBorder == NULL)
  2065.         {
  2066.             if (!m_rectBorder.IsRectNull())
  2067.             {
  2068.                 // releasing all border space -- recalc needed
  2069. #ifdef _MAC
  2070.                 if (m_pViewActive->GetParentFrame() == GetTopLevelFrame())
  2071.                 {
  2072.                     // SDI
  2073.                     ASSERT((GetExStyle() & WS_EX_MDIFRAME) == 0);
  2074.  
  2075.                     CRect rcNew;
  2076.                     GetWindowRect(&rcNew);
  2077.                     rcNew += &m_rectBorder;
  2078.                     m_bInRecalcLayout = TRUE;
  2079.                     MoveWindow(rcNew);
  2080.                     m_bInRecalcLayout = FALSE;
  2081.                 }
  2082. #endif
  2083.                 m_rectBorder.SetRectEmpty();
  2084.                 return TRUE;
  2085.             }
  2086.             // original rect is empty & lpRectBorder is NULL, no recalc needed
  2087.             return FALSE;
  2088.         }
  2089.         if (!_AfxIdenticalRect(m_rectBorder, lpRectBorder))
  2090.         {
  2091.             // the rects are different -- recalc needed
  2092. #ifdef _MAC
  2093.             if (m_pViewActive->GetParentFrame() == GetTopLevelFrame())
  2094.             {
  2095.                 // SDI
  2096.                 ASSERT((GetExStyle() & WS_EX_MDIFRAME) == 0);
  2097.  
  2098.                 CRect rcNew;
  2099.                 GetWindowRect(&rcNew);
  2100.                 rcNew += &m_rectBorder;
  2101.                 rcNew -= lpRectBorder;
  2102.                 MoveWindow(rcNew);
  2103.                 m_rectBorder.CopyRect(lpRectBorder);
  2104.                 return FALSE;
  2105.             }
  2106. #endif
  2107.             m_rectBorder.CopyRect(lpRectBorder);
  2108.             return TRUE;
  2109.         }
  2110.         return FALSE;   // no recalc needed
  2111.  
  2112.     default:
  2113.         ASSERT(FALSE);  // invalid CFrameWnd::BorderCmd
  2114.     }
  2115.  
  2116.     return TRUE;
  2117. }
  2118.  
  2119. void CFrameWnd::OnSize(UINT nType, int cx, int cy)
  2120. {
  2121.     CWnd::OnSize(nType, cx, cy);    // important for MDI Children
  2122.     if (nType != SIZE_MINIMIZED)
  2123.         RecalcLayout();
  2124. }
  2125.  
  2126. BOOL CFrameWnd::OnEraseBkgnd(CDC* pDC)
  2127. {
  2128.     if (m_pViewActive != NULL)
  2129.         return TRUE;        // active view will erase/paint itself
  2130.     // for view-less frame just use the default background fill
  2131.     return CWnd::OnEraseBkgnd(pDC);
  2132. }
  2133.  
  2134. #ifndef _MAC
  2135. LRESULT CFrameWnd::OnRegisteredMouseWheel(WPARAM wParam, LPARAM lParam)
  2136. {
  2137.     // convert from MSH_MOUSEWHEEL to WM_MOUSEWHEEL
  2138.  
  2139.     WORD keyState = 0;
  2140.     keyState |= (::GetKeyState(VK_CONTROL) < 0) ? MK_CONTROL : 0;
  2141.     keyState |= (::GetKeyState(VK_SHIFT) < 0) ? MK_SHIFT : 0;
  2142.  
  2143.     LRESULT lResult;
  2144.     HWND hwFocus = ::GetFocus();
  2145.     const HWND hwDesktop = ::GetDesktopWindow();
  2146.  
  2147.     if (hwFocus == NULL)
  2148.         lResult = SendMessage(WM_MOUSEWHEEL, (wParam << 16) | keyState, lParam);
  2149.     else
  2150.     {
  2151.         do {
  2152.             lParam = ::SendMessage(hwFocus, WM_MOUSEWHEEL,
  2153.                 (wParam << 16) | keyState, lParam);
  2154.             hwFocus = ::GetParent(hwFocus);
  2155.         }
  2156.         while (lParam == 0 && hwFocus != NULL && hwFocus != hwDesktop);
  2157.     }
  2158.     return lResult;
  2159. }
  2160. #endif
  2161.  
  2162. #ifdef _MAC
  2163. // With Macintosh sizeboxes, it's possible for there to be uncovered areas on
  2164. // the frame's client area after RepositionBars.  We add this paint handler
  2165. // to redraw only those uncovered areas.  Because we may not be a
  2166. // WS_CLIPCHILDREN window, we go to some effort to avoid drawing on top of
  2167. // our children
  2168. void CFrameWnd::OnPaint()
  2169. {
  2170.     if (m_pViewActive == NULL)
  2171.     {
  2172.         CWnd::OnPaint();
  2173.         return;
  2174.     }
  2175.  
  2176.     CWnd* pWnd;
  2177.     CRgn rgnUpdate;
  2178.     CRgn rgn;
  2179.     CRect rect;
  2180.  
  2181.     CPaintDC dc(this);
  2182.  
  2183.     // compute the area not covered by child windows in screen coordinates
  2184.     rect = dc.m_ps.rcPaint;
  2185.     ClientToScreen(&rect);
  2186.     rgnUpdate.CreateRectRgnIndirect(&rect);
  2187.     rgn.CreateRectRgn(0, 0, 0, 0);
  2188.     for (pWnd = GetWindow(GW_CHILD); pWnd != NULL;
  2189.         pWnd = pWnd->GetWindow(GW_HWNDNEXT))
  2190.     {
  2191.         pWnd->GetWindowRect(&rect);
  2192.         rgn.SetRectRgn(&rect);
  2193.         if (rgnUpdate.CombineRgn(&rgnUpdate, &rgn, RGN_DIFF) == NULLREGION)
  2194.             return;
  2195.     }
  2196.  
  2197.     // convert the bounding box of the uncovered region into client
  2198.     // coordinates and fill it with a nice color
  2199.     rgnUpdate.GetRgnBox(&rect);
  2200.     BOOL bMono = AfxCheckMonochrome(&rect);
  2201.     ScreenToClient(&rect);
  2202.     dc.FillSolidRect(rect, bMono ? RGB(0xFF, 0xFF, 0xFF) : afxData.clrBtnFace);
  2203. }
  2204. #endif
  2205.  
  2206.  
  2207. void CFrameWnd::ActivateFrame(int nCmdShow)
  2208.     // nCmdShow is the normal show mode this frame should be in
  2209. {
  2210.     // translate default nCmdShow (-1)
  2211.     if (nCmdShow == -1)
  2212.     {
  2213.         if (!IsWindowVisible())
  2214.             nCmdShow = SW_SHOWNORMAL;
  2215.         else if (IsIconic())
  2216.             nCmdShow = SW_RESTORE;
  2217.     }
  2218.  
  2219.     // bring to top before showing
  2220.     BringToTop(nCmdShow);
  2221.  
  2222.     if (nCmdShow != -1)
  2223.     {
  2224.         // show the window as specified
  2225.         ShowWindow(nCmdShow);
  2226.  
  2227.         // and finally, bring to top after showing
  2228.         BringToTop(nCmdShow);
  2229.     }
  2230. }
  2231.  
  2232. void CFrameWnd::BringToTop(int nCmdShow)
  2233. {
  2234.     // place the window on top except for certain nCmdShow
  2235.     if (nCmdShow != SW_HIDE &&
  2236.         nCmdShow != SW_MINIMIZE && nCmdShow != SW_SHOWMINNOACTIVE &&
  2237.         nCmdShow != SW_SHOWNA && nCmdShow != SW_SHOWNOACTIVATE)
  2238.     {
  2239.         // if no last active popup, it will return m_hWnd
  2240.         HWND hWndLastPop = ::GetLastActivePopup(m_hWnd);
  2241.         ::BringWindowToTop(hWndLastPop);
  2242.     }
  2243. }
  2244.  
  2245. /////////////////////////////////////////////////////////////////////////////
  2246. // CFrameWnd Diagnostics
  2247.  
  2248. #ifdef _DEBUG
  2249. void CFrameWnd::AssertValid() const
  2250. {
  2251.     CWnd::AssertValid();
  2252.     if (m_pViewActive != NULL)
  2253.         ASSERT_VALID(m_pViewActive);
  2254. }
  2255.  
  2256. void CFrameWnd::Dump(CDumpContext& dc) const
  2257. {
  2258.     CWnd::Dump(dc);
  2259.  
  2260.     dc << "m_hAccelTable = " << (UINT)m_hAccelTable;
  2261.     dc << "\nm_nWindow = " << m_nWindow;
  2262.     dc << "\nm_nIDHelp = " << m_nIDHelp;
  2263.     dc << "\nm_nIDTracking = " << m_nIDTracking;
  2264.     dc << "\nm_nIDLastMessage = " << m_nIDLastMessage;
  2265.     if (m_pViewActive != NULL)
  2266.         dc << "\nwith active view: " << m_pViewActive;
  2267.     else
  2268.         dc << "\nno active view";
  2269.  
  2270.     dc << "\n";
  2271. }
  2272. #endif //_DEBUG
  2273.  
  2274. /////////////////////////////////////////////////////////////////////////////
  2275. // CControlBar segmentation
  2276.  
  2277. CFrameWnd* CControlBar::GetDockingFrame() const
  2278. {
  2279.     CFrameWnd* pFrameWnd = GetParentFrame();
  2280.     if (pFrameWnd == NULL)
  2281.         pFrameWnd = m_pDockSite;
  2282.  
  2283.     ASSERT(pFrameWnd != NULL);
  2284.     ASSERT_KINDOF(CFrameWnd, pFrameWnd);
  2285.     return pFrameWnd;
  2286. }
  2287.  
  2288. BOOL CControlBar::IsFloating() const
  2289. {
  2290.     if (IsDockBar())
  2291.         return ((CDockBar*)this)->m_bFloating;
  2292.     else
  2293.         return m_pDockBar != NULL && m_pDockBar->m_bFloating;
  2294. }
  2295.  
  2296. #ifdef AFX_INIT_SEG
  2297. #pragma code_seg(AFX_INIT_SEG)
  2298. #endif
  2299.  
  2300. // in this file for IsKindOf library granularity (IsKindOf references these)
  2301. IMPLEMENT_DYNCREATE(CFrameWnd, CWnd)
  2302. IMPLEMENT_DYNAMIC(CView, CWnd)
  2303. IMPLEMENT_DYNAMIC(CControlBar, CWnd)
  2304.  
  2305. /////////////////////////////////////////////////////////////////////////////
  2306.