home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 17.ddi / MFC / SRC / WINFRM.CP_ / WINFRM.CP
Encoding:
Text File  |  1993-02-08  |  28.6 KB  |  1,055 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library. 
  2. // Copyright (C) 1992 Microsoft Corporation 
  3. // All rights reserved. 
  4. //  
  5. // This source code is only intended as a supplement to the 
  6. // Microsoft Foundation Classes Reference and Microsoft 
  7. // QuickHelp and/or WinHelp 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_CORE2_SEG
  15. #pragma code_seg(AFX_CORE2_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char BASED_CODE THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CRect for creating windows with the default position/size
  25.  
  26. const CRect AFXAPI_DATA CFrameWnd::rectDefault(CW_USEDEFAULT, CW_USEDEFAULT,
  27.     0 /* 2*CW_USEDEFAULT */, 0 /* 2*CW_USEDEFAULT */);
  28.  
  29. /////////////////////////////////////////////////////////////////////////////
  30. // CFrameWnd
  31.  
  32. IMPLEMENT_DYNCREATE(CFrameWnd, CWnd)
  33. IMPLEMENT_DYNAMIC(CView, CWnd)  // in this file for IsKindOf .OBJ granularity
  34.  
  35. BEGIN_MESSAGE_MAP(CFrameWnd, CWnd)
  36.     //{{AFX_MSG_MAP(CFrameWnd)
  37.     // windows messages
  38.     ON_WM_INITMENUPOPUP()
  39.     ON_WM_MENUSELECT()
  40.     ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString)
  41.     ON_WM_ENTERIDLE()
  42.     ON_WM_HSCROLL()
  43.     ON_WM_VSCROLL()
  44.     ON_WM_SETFOCUS()
  45.     ON_WM_CREATE()
  46.     ON_WM_DESTROY()
  47.     ON_WM_NCDESTROY()
  48.     ON_WM_CLOSE()
  49.     ON_WM_SIZE()
  50.     ON_WM_ERASEBKGND()
  51.     ON_WM_ACTIVATE()
  52.     ON_WM_ACTIVATEAPP()
  53.     ON_WM_SYSCOMMAND()
  54.     ON_WM_DROPFILES()
  55.     ON_WM_QUERYENDSESSION()
  56.     ON_WM_SETCURSOR()
  57.     ON_WM_SYSCOLORCHANGE()
  58.  
  59.     ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
  60.     ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
  61.     ON_MESSAGE(WM_DDE_INITIATE, OnDDEInitiate)
  62.     ON_MESSAGE(WM_DDE_EXECUTE, OnDDEExecute)
  63.     ON_MESSAGE(WM_DDE_TERMINATE, OnDDETerminate)
  64.  
  65.     // turning on and off standard frame gadgetry
  66.     ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateControlBarMenu)
  67.     ON_COMMAND_EX(ID_VIEW_STATUS_BAR, OnBarCheck)
  68.     ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLBAR, OnUpdateControlBarMenu)
  69.     ON_COMMAND_EX(ID_VIEW_TOOLBAR, OnBarCheck)
  70.  
  71.     // turning on and off standard mode indicators
  72.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_CAPS, OnUpdateKeyIndicator)
  73.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_NUM, OnUpdateKeyIndicator)
  74.     ON_UPDATE_COMMAND_UI(ID_INDICATOR_SCRL, OnUpdateKeyIndicator)
  75.     //}}AFX_MSG_MAP
  76. END_MESSAGE_MAP()
  77.  
  78. /////////////////////////////////////////////////////////////////////////////
  79. // CFrameWnd construction/destruction
  80.  
  81. CFrameWnd::CFrameWnd()
  82. {
  83.     AFX_ZERO_INIT_OBJECT(CWnd);
  84.     ASSERT(m_hWnd == NULL);
  85.     m_nWindow = -1; // unknown
  86.     m_bAutoMenuEnable = TRUE;       // auto enable on by default
  87.     m_lpfnCloseProc = NULL;
  88. }
  89.  
  90. /////////////////////////////////////////////////////////////////////////////
  91. // Special processing etc
  92.  
  93. BOOL CFrameWnd::LoadAccelTable(LPCSTR lpszResourceName)
  94. {
  95.     ASSERT(m_hAccelTable == NULL);  // only do once
  96.     ASSERT(lpszResourceName != NULL);
  97.  
  98. #ifndef _AFXDLL
  99.     HINSTANCE hInst = AfxGetResourceHandle();
  100. #else
  101.     HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_ACCELERATOR);
  102. #endif
  103.     m_hAccelTable = ::LoadAccelerators(hInst, lpszResourceName);
  104.     return (m_hAccelTable != NULL);
  105. }
  106.  
  107. BOOL CFrameWnd::PreTranslateMessage(MSG* pMsg)
  108. {
  109.     // check for special cancel modes for ComboBoxes
  110.     if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_NCLBUTTONDOWN)
  111.         _AfxCancelModes(pMsg->hwnd);    // filter clicks
  112.  
  113.     return (m_hAccelTable != NULL &&
  114.       ::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg));
  115. }
  116.  
  117. void CFrameWnd::PostNcDestroy()
  118. {
  119.     // default for frame windows is to allocate them on the heap
  120.     //  the default post-cleanup is to 'delete this'.
  121.     // never explicitly call 'delete' on a CFrameWnd, use DestroyWindow instead
  122.     delete this;
  123. }
  124.  
  125. /////////////////////////////////////////////////////////////////////////////
  126. // CFrameWnd support for context sensitive help.
  127.  
  128. BOOL CFrameWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  129. {
  130.     if (AfxGetApp()->m_bHelpMode)
  131.     {
  132.         SetCursor(AfxGetApp()->m_hcurHelp);
  133.         return TRUE;
  134.     }
  135.     return CWnd::OnSetCursor(pWnd, nHitTest, message);
  136. }
  137.  
  138. BOOL CFrameWnd::IsTracking() const
  139. {
  140.     return m_nIDTracking != 0 &&
  141.         m_nIDTracking != AFX_IDS_HELPMODEMESSAGE &&
  142.         m_nIDTracking != AFX_IDS_IDLEMESSAGE;
  143. }
  144.  
  145. LRESULT CFrameWnd::OnCommandHelp(WPARAM, LPARAM lParam)
  146. {
  147.     if (lParam == 0)
  148.     {
  149.         if (IsTracking())
  150.             lParam = HID_BASE_COMMAND+m_nIDTracking;
  151.         else
  152.             lParam = HID_BASE_RESOURCE+m_nIDHelp;
  153.     }
  154.     if (lParam != 0)
  155.     {
  156.         AfxGetApp()->WinHelp(lParam);
  157.         return TRUE;
  158.     }
  159.     return FALSE;
  160. }
  161.  
  162. LRESULT CFrameWnd::OnHelpHitTest(WPARAM, LPARAM)
  163. {
  164.     if (m_nIDHelp != 0)
  165.         return HID_BASE_RESOURCE+m_nIDHelp;
  166.     else
  167.         return 0;
  168. }
  169.  
  170. BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
  171.     // return TRUE if command invocation was attempted
  172. {
  173.     HWND hWndCtrl = (HWND)LOWORD(lParam);
  174.     UINT nID = LOWORD(wParam);
  175.     if (AfxGetApp()->m_bHelpMode && hWndCtrl == NULL &&
  176.         nID != ID_HELP && nID != ID_DEFAULT_HELP)
  177.     {
  178.         ASSERT(nID != 0);
  179.         if (!SendMessage(WM_COMMANDHELP, 0, HID_BASE_COMMAND+nID))
  180.             SendMessage(WM_COMMAND, ID_DEFAULT_HELP);
  181.         return TRUE;
  182.     }
  183.     return CWnd::OnCommand(wParam, lParam);
  184. }
  185.  
  186. /////////////////////////////////////////////////////////////////////////////
  187. // CFrameWnd second phase creation
  188.  
  189. BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
  190. {
  191.     if (cs.lpszClass == NULL)
  192.         cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background
  193.     return TRUE;
  194. }
  195.  
  196. BOOL CFrameWnd::Create(LPCSTR lpszClassName,
  197.     LPCSTR lpszWindowName,
  198.     DWORD dwStyle,
  199.     const RECT& rect,
  200.     CWnd* pParentWnd,
  201.     LPCSTR lpszMenuName,
  202.     DWORD dwExStyle,
  203.     CCreateContext* pContext)
  204. {
  205.     if (pParentWnd == NULL)
  206.         pParentWnd = (CFrameWnd*)AfxGetApp()->m_pMainWnd;
  207.  
  208.     HMENU hMenu = NULL;
  209.     if (lpszMenuName != NULL)
  210.     {
  211.         // load in a menu that will get destroyed when window gets destroyed
  212. #ifndef _AFXDLL
  213.         HINSTANCE hInst = AfxGetResourceHandle();
  214. #else
  215.         HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU);
  216. #endif
  217.         if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)
  218.         {
  219.             TRACE0("Warning: failed to load menu for CFrameWnd\n");
  220.             PostNcDestroy();            // perhaps delete the C++ object
  221.             return FALSE;
  222.         }
  223.     }
  224.  
  225.     if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
  226.         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  227.         pParentWnd->GetSafeHwnd(), hMenu, (LPSTR)pContext))
  228.     {
  229.         TRACE0("Warning: failed to create CFrameWnd\n");
  230.         return FALSE;
  231.     }
  232.     return TRUE;
  233. }
  234.  
  235.  
  236. BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext)
  237. {
  238.     // default create client will create a view if asked for it
  239.     if (pContext != NULL)
  240.     {
  241.         // try to create view object from RuntimeClass
  242.         if (pContext->m_pNewViewClass != NULL)
  243.         {
  244.             CWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();
  245.                 // NOTE: can be a CWnd with PostNcDestroy self cleanup
  246.  
  247.             if (pView == NULL)
  248.             {
  249.                 TRACE1("Warning: Dynamic create of view type %Fs failed\n",
  250.                     pContext->m_pNewViewClass->m_lpszClassName);
  251.                 return FALSE;
  252.             }
  253.             ASSERT(pView->IsKindOf(RUNTIME_CLASS(CWnd)));
  254.             // Views are always created with a border !
  255.             if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
  256.                 CRect(0,0,0,0), this, AFX_IDW_PANE_FIRST, pContext))
  257.             {
  258.                 TRACE0("Warning: couldn't create view for frame\n");
  259.                 return FALSE;       // can't continue without a view
  260.             }
  261.         }
  262.     }
  263.  
  264.     return TRUE;
  265. }
  266.  
  267. int CFrameWnd::OnCreate(LPCREATESTRUCT lpcs)
  268. {
  269.     CCreateContext* pContext = (CCreateContext*)
  270.         _AfxGetPtrFromFarPtr(lpcs->lpCreateParams);
  271.  
  272.     return OnCreateHelper(lpcs, pContext);
  273. }
  274.  
  275. int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext)
  276. {
  277.     if (CWnd::OnCreate(lpcs) == -1)
  278.         return -1;
  279.  
  280.     // create special children first
  281.     if (!OnCreateClient(lpcs, pContext))
  282.     {
  283.         TRACE0("Failed to create client pane/view for frame\n");
  284.         return -1;
  285.     }
  286.  
  287.     // post message for initial message string
  288.     PostMessage(WM_SETMESSAGESTRING, (WPARAM)AFX_IDS_IDLEMESSAGE, 0L);
  289.     return 0;   // create ok
  290. }
  291.  
  292. LPCSTR CFrameWnd::GetIconWndClass(DWORD dwDefaultStyle, UINT nIDResource)
  293. {
  294.     ASSERT_VALID_IDR(nIDResource);
  295. #ifndef _AFXDLL
  296.     HINSTANCE hInst = AfxGetResourceHandle();
  297. #else
  298.     HINSTANCE hInst = AfxFindResourceHandle(
  299.         MAKEINTRESOURCE(nIDResource), RT_GROUP_ICON);
  300. #endif
  301.     HICON hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDResource));
  302.     if (hIcon != NULL)
  303.     {
  304.         CREATESTRUCT cs;
  305.         memset(&cs, 0, sizeof(CREATESTRUCT));
  306.         cs.style = dwDefaultStyle;
  307.         PreCreateWindow(cs);
  308.             // will fill lpszClassName with default WNDCLASS name
  309.             // ignore instance handle from PreCreateWindow.
  310.  
  311.         WNDCLASS wndcls;
  312.         if (cs.lpszClass != NULL &&
  313.             GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wndcls) &&
  314.             wndcls.hIcon != hIcon)
  315.         {
  316.             // register a very similar WNDCLASS
  317.             return AfxRegisterWndClass(wndcls.style,
  318.                 wndcls.hCursor, wndcls.hbrBackground, hIcon);
  319.         }
  320.     }
  321.     return NULL;        // just use the default
  322. }
  323.  
  324. BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
  325.     CWnd* pParentWnd, CCreateContext* pContext)
  326. {
  327.     // only do this once
  328.     ASSERT_VALID_IDR(nIDResource);
  329.     ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
  330.  
  331.     m_nIDHelp = nIDResource;    // ID for help context (+HID_BASE_RESOURCE)
  332.  
  333.     CString strFullString, strTitle;
  334.     if (strFullString.LoadString(nIDResource))
  335.         AfxExtractSubString(strTitle, strFullString, 0);    // first sub-string
  336.  
  337.     if (!Create(GetIconWndClass(dwDefaultStyle, nIDResource),
  338.       strTitle, dwDefaultStyle, rectDefault,
  339.       pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
  340.         return FALSE;   // will self destruct on failure normally
  341.  
  342.     LoadAccelTable(MAKEINTRESOURCE(nIDResource));
  343.  
  344.     if (pContext == NULL)   // send initial update
  345.         SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE);
  346.  
  347.     return TRUE;
  348. }
  349.  
  350.  
  351.  
  352. /////////////////////////////////////////////////////////////////////////////
  353. // CFrameWnd closing down
  354.  
  355.  
  356. void CFrameWnd::OnClose()
  357. {
  358.     if (m_lpfnCloseProc != NULL && !(*m_lpfnCloseProc)(this))
  359.         return;
  360.  
  361.     // Note: only queries the active document
  362.     CDocument* pDocument = GetActiveDocument();
  363.     if (pDocument != NULL)
  364.     {
  365.         if (!pDocument->CanCloseFrame(this))
  366.             return;     // don't close it
  367.     }
  368.     else if (AfxGetApp()->m_pMainWnd == this)
  369.     {
  370.         // try to close all documents
  371.         if (!AfxGetApp()->SaveAllModified())
  372.             return;     // don't close it
  373.     }
  374.  
  375.     DestroyWindow();    // close it
  376. }
  377.  
  378. void CFrameWnd::OnDestroy()
  379. {
  380.     // Automatically quit when the main window is destroyed.
  381.     if (AfxGetApp()->m_pMainWnd == this)
  382.     {
  383.         // m_pMainWnd should not be a child or owned popup!
  384.         ASSERT(::GetParent(m_hWnd) == NULL);
  385.         // closing the main application window
  386.         ::WinHelp(m_hWnd, NULL, HELP_QUIT, 0L);
  387.         // will call PostQuitMessage in CWnd::OnNcDestroy
  388.     }
  389.     CWnd::OnDestroy();
  390. }
  391.  
  392. void CFrameWnd::OnNcDestroy()
  393. {
  394.     // WM_NCDESTROY is the absolute LAST message sent.
  395. #ifndef _USRDLL
  396.     if (AfxGetApp()->m_pMainWnd == this)
  397.         ::PostQuitMessage(0);
  398. #endif
  399.     CWnd::OnNcDestroy();        // does detach and PostNcDestroy cleanup
  400. }
  401.  
  402. /////////////////////////////////////////////////////////////////////////////
  403. // CFrameWnd command/message routing
  404.  
  405. BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
  406.     AFX_CMDHANDLERINFO* pHandlerInfo)
  407. {
  408.     CView* pActiveView = GetActiveView();
  409.     // pump through current view FIRST
  410.     if (pActiveView != NULL &&
  411.       pActiveView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  412.         return TRUE;
  413.  
  414.     // then pump through frame
  415.     if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  416.         return TRUE;
  417.  
  418.     // last but not least, pump through app
  419.     CWinApp* pApp = AfxGetApp();
  420.     if (pApp != NULL &&
  421.       pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  422.         return TRUE;
  423.  
  424.     return FALSE;
  425. }
  426.  
  427. // Delegate scroll messages to active view as well
  428. void CFrameWnd::OnHScroll(UINT, UINT, CScrollBar*)
  429. {
  430.     CWnd* pActiveView = GetActiveView();
  431.     if (pActiveView != NULL)
  432.     {
  433.         const MSG* pMsg = GetCurrentMessage();
  434.         pActiveView->SendMessage(WM_HSCROLL, pMsg->wParam, pMsg->lParam);
  435.     }
  436. }
  437.  
  438. void CFrameWnd::OnVScroll(UINT, UINT, CScrollBar*)
  439. {
  440.     CWnd* pActiveView = GetActiveView();
  441.     if (pActiveView != NULL)
  442.     {
  443.         const MSG* pMsg = GetCurrentMessage();
  444.         pActiveView->SendMessage(WM_VSCROLL, pMsg->wParam, pMsg->lParam);
  445.     }
  446. }
  447.  
  448.  
  449. // When frame gets activated, re-activate current view
  450. void CFrameWnd::OnActivate(UINT nState, CWnd*, BOOL bMinimized)
  451. {
  452.     if (nState != WA_INACTIVE && !bMinimized)
  453.     {
  454.         CView* pActiveView = GetActiveView();
  455.         if (pActiveView != NULL)
  456.             pActiveView->OnActivateView(TRUE, pActiveView, pActiveView);
  457.     }
  458. }
  459.  
  460.  
  461. void CFrameWnd::OnActivateApp(BOOL bActive, HTASK hTask)
  462. {
  463.     if (!bActive && AfxGetApp()->m_bHelpMode)
  464.     {
  465.         MSG msg;
  466.         while (::PeekMessage(&msg, NULL, WM_EXITHELPMODE, WM_EXITHELPMODE,
  467.                 PM_REMOVE|PM_NOYIELD))
  468.             ;
  469.         ASSERT(hTask != ::GetCurrentTask());
  470.         VERIFY(::PostAppMessage(::GetCurrentTask(), WM_EXITHELPMODE, 0, 0));
  471.     }
  472.     CWnd::OnActivateApp(bActive, hTask);
  473. }
  474.  
  475. void CFrameWnd::OnSysCommand(UINT nID, LONG lParam)
  476. {
  477.     if (!AfxGetApp()->m_bHelpMode)
  478.     {
  479.         // don't interfere with system commands if not in help mode
  480.         CWnd::OnSysCommand(nID, lParam);
  481.         return;
  482.     }
  483.  
  484.     switch (nID & 0xFFF0)
  485.     {
  486.     case SC_SIZE:
  487.     case SC_MOVE:
  488.     case SC_MINIMIZE:
  489.     case SC_MAXIMIZE:
  490.     case SC_NEXTWINDOW:
  491.     case SC_PREVWINDOW:
  492.     case SC_CLOSE:
  493.     case SC_RESTORE:
  494.     case SC_TASKLIST:
  495.         if (!SendMessage(WM_COMMANDHELP, 0,
  496.           HID_BASE_COMMAND+ID_COMMAND_FROM_SC(nID & 0xFFF0)))
  497.             SendMessage(WM_COMMAND, ID_DEFAULT_HELP);
  498.         break;
  499.  
  500.     default:
  501.         // don't interfere with system commands we don't know about
  502.         CWnd::OnSysCommand(nID, lParam);
  503.         break;
  504.     }
  505. }
  506.  
  507. /////////////////////////////////////////////////////////////////////////////
  508. // default frame processing
  509.  
  510. // default drop processing will try to open the file
  511. void CFrameWnd::OnDropFiles(HDROP hDropInfo)
  512. {
  513.     SetActiveWindow();      // activate us first !
  514.     UINT nFiles = ::DragQueryFile(hDropInfo, -1, NULL, 0);
  515.  
  516.     for (UINT iFile = 0; iFile < nFiles; iFile++)
  517.     {
  518.         char szFileName[_MAX_PATH];
  519.         ::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
  520.         AfxGetApp()->OpenDocumentFile(szFileName);
  521.     }
  522.     ::DragFinish(hDropInfo);
  523. }
  524.  
  525. // query end session for main frame will try to close it all down
  526. BOOL CFrameWnd::OnQueryEndSession()
  527. {
  528.     if (AfxGetApp()->m_pMainWnd == this)
  529.         return AfxGetApp()->SaveAllModified();
  530.     return CWnd::OnQueryEndSession();
  531. }
  532. // if end-session comes through we will _not_ destroy anything
  533.  
  534. /////////////////////////////////////////////////////////////////////////////
  535. // Support for Shell DDE Execute messages
  536.  
  537. LRESULT CFrameWnd::OnDDEInitiate(WPARAM wParam, LPARAM lParam)
  538. {
  539.     CWinApp* pApp = AfxGetApp();
  540.     if ((ATOM)LOWORD(lParam) == pApp->m_atomApp &&
  541.       (ATOM)HIWORD(lParam) == pApp->m_atomSystemTopic)
  542.         ::SendMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hWnd, lParam);
  543.     return 0L;
  544. }
  545.  
  546. // always ACK the execute command - even if we do nothing
  547. LRESULT CFrameWnd::OnDDEExecute(WPARAM wParam, LPARAM lParam)
  548. {
  549.     HGLOBAL hData = (HGLOBAL)HIWORD(lParam);
  550.     char szCommand[_MAX_PATH * 2];
  551.     LPCSTR lpsz = (LPCSTR)GlobalLock(hData);
  552.     _AfxStrCpy(szCommand, lpsz, sizeof(szCommand));
  553.     GlobalUnlock(hData);
  554.     // acknowedge now - before attempting to execute
  555.     ::PostMessage((HWND)wParam, WM_DDE_ACK, (WPARAM)m_hWnd,
  556.         MAKELPARAM(0x8000, hData));
  557.     if (!AfxGetApp()->OnDDECommand(szCommand))
  558.         TRACE1("Error: failed to execute DDE command '%s'\n", szCommand);
  559.     return 0L;
  560. }
  561.  
  562. LRESULT CFrameWnd::OnDDETerminate(WPARAM wParam, LPARAM lParam)
  563. {
  564.     ::PostMessage((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)m_hWnd, lParam);
  565.     return 0L;
  566. }
  567.  
  568. /////////////////////////////////////////////////////////////////////////////
  569. // CFrameWnd attributes
  570.  
  571. CView* CFrameWnd::GetActiveView() const
  572. {
  573.     ASSERT(m_pViewActive == NULL ||
  574.         m_pViewActive->IsKindOf(RUNTIME_CLASS(CView)));
  575.     return m_pViewActive;
  576. }
  577.  
  578. void CFrameWnd::SetActiveView(CView* pViewNew)
  579. {
  580. #ifdef _DEBUG
  581.     if (pViewNew != NULL)
  582.     {
  583.         ASSERT(IsChild(pViewNew));
  584.         ASSERT(pViewNew->IsKindOf(RUNTIME_CLASS(CView)));
  585.     }
  586. #endif //_DEBUG
  587.  
  588.     CView* pViewOld = m_pViewActive;
  589.     if (pViewNew == pViewOld)
  590.         return;     // do not re-activate if SetActiveView called more than once
  591.  
  592.     m_pViewActive = NULL;   // no active for the following processing
  593.  
  594.     // deactivate the old one
  595.     if (pViewOld != NULL)
  596.         pViewOld->OnActivateView(FALSE, pViewNew, pViewOld);
  597.  
  598.     // if the OnActivateView moves the active window,
  599.     //    that will veto this change
  600.     if (m_pViewActive != NULL)
  601.         return;     // already set
  602.     m_pViewActive = pViewNew;
  603.  
  604.     // activate
  605.     if (pViewNew != NULL)
  606.         pViewNew->OnActivateView(TRUE, pViewNew, pViewOld);
  607. }
  608.  
  609. /////////////////////////////////////////////////////////////////////////////
  610. // Special view swapping/activation
  611.  
  612. void CFrameWnd::OnSetFocus(CWnd* pOldWnd)
  613. {
  614.     if (m_pViewActive != NULL)
  615.         m_pViewActive->SetFocus();
  616.     else
  617.         CWnd::OnSetFocus(pOldWnd);
  618. }
  619.  
  620. CDocument* CFrameWnd::GetActiveDocument()
  621. {
  622.     ASSERT_VALID(this);
  623.     CView* pView = GetActiveView();
  624.     if (pView != NULL)
  625.         return pView->GetDocument();
  626.     return NULL;
  627. }
  628.  
  629.  
  630.  
  631. /////////////////////////////////////////////////////////////////////////////
  632. // Command prompts
  633.  
  634. void CFrameWnd::OnInitMenuPopup(CMenu* pMenu, UINT, BOOL bSysMenu)
  635. {
  636.     _AfxCancelModes(m_hWnd);
  637.  
  638.     if (bSysMenu)
  639.         return;     // don't support system menu
  640.  
  641.     ASSERT(pMenu != NULL);
  642.     // check the enabled state of various menu items
  643.  
  644.     CCmdUI state;
  645.     state.m_pMenu = pMenu;
  646.     ASSERT(state.m_pOther == NULL);
  647.  
  648.     state.m_nIndexMax = pMenu->GetMenuItemCount();
  649.     for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
  650.       state.m_nIndex++)
  651.     {
  652.         state.m_nID = pMenu->GetMenuItemID(state.m_nIndex);
  653.         if (state.m_nID == 0)
  654.             continue; // menu separator or invalid cmd - ignore it
  655.  
  656.         ASSERT(state.m_pOther == NULL);
  657.         ASSERT(state.m_pMenu != NULL);
  658.         if (state.m_nID == (UINT)-1)
  659.         {
  660.             // possibly a popup menu, route to first item of that popup
  661.             state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex);
  662.             if (state.m_pSubMenu == NULL ||
  663.                 (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
  664.                 state.m_nID == (UINT)-1)
  665.             {
  666.                 continue;       // first item of popup can't be routed to
  667.             }
  668.             state.DoUpdate(this, FALSE);    // popups are never auto disabled
  669.         }
  670.         else
  671.         {
  672.             // normal menu item
  673.             // Auto enable/disable if frame window has 'm_bAutoMenuEnable'
  674.             //    set and command is _not_ a system command.
  675.             state.m_pSubMenu = NULL;
  676.             state.DoUpdate(this, m_bAutoMenuEnable && state.m_nID < 0xF000);
  677.         }
  678.     }
  679. }
  680.  
  681. void CFrameWnd::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU /*hSysMenu*/)
  682. {
  683.     // set the tracking state (update on idle)
  684.     if (nFlags == 0xFFFF)
  685.     {
  686.         // cancel menu operation (go back to idle now)
  687.         if (!AfxGetApp()->m_bHelpMode)
  688.             m_nIDTracking = AFX_IDS_IDLEMESSAGE;
  689.         else
  690.             m_nIDTracking = AFX_IDS_HELPMODEMESSAGE;
  691.         OnSetMessageString(m_nIDTracking, NULL);    // set string now
  692.         ASSERT(m_nIDTracking == m_nIDLastMessage);
  693.     }
  694.     else if (nItemID == 0 ||
  695.         nFlags & (MF_SEPARATOR|MF_POPUP|MF_MENUBREAK|MF_MENUBARBREAK))
  696.     {
  697.         // nothing should be displayed
  698.         m_nIDTracking = 0;
  699.     }
  700.     else if (nItemID >= 0xF000 && nItemID < 0xF1F0) // max of 31 SC_s
  701.     {
  702.         // special strings table entries for system commands
  703.         m_nIDTracking = ID_COMMAND_FROM_SC(nItemID);
  704.         ASSERT(m_nIDTracking >= AFX_IDS_SCFIRST &&
  705.             m_nIDTracking < AFX_IDS_SCFIRST + 31);
  706.     }
  707.     else if (nItemID >= AFX_IDM_FIRST_MDICHILD)
  708.     {
  709.         // all MDI Child windows map to the same help id
  710.         m_nIDTracking = AFX_IDS_MDICHILD;
  711.     }
  712.     else
  713.     {
  714.         // track on idle
  715.         m_nIDTracking = nItemID;
  716.     }
  717. }
  718.  
  719. LRESULT CFrameWnd::OnSetMessageString(WPARAM wParam, LPARAM lParam)
  720. {
  721.     CWnd* pMessageBar = GetMessageBar();
  722.     if (pMessageBar != NULL)
  723.     {
  724.         LPCSTR lpsz = NULL;
  725.         char szBuffer[256];
  726.         // set the message bar text
  727.         if (lParam != NULL)
  728.         {
  729.             ASSERT(wParam == 0);    // can't have both an ID and a string
  730.             // set an explicit string
  731.             lpsz = (LPCSTR)lParam;
  732.         }
  733.         else if (wParam != 0)
  734.         {
  735.             // use the wParam as a string ID
  736.             if (_AfxLoadString(wParam, szBuffer) != 0)
  737.                 lpsz = szBuffer;
  738.             else
  739.                 TRACE1("Warning: no message line prompt for ID 0x%04X\n",
  740.                     (UINT)wParam);
  741.         }
  742.  
  743.         pMessageBar->SetWindowText(lpsz);
  744.     }
  745.  
  746.     UINT nIDLast = m_nIDLastMessage;
  747.     m_nIDLastMessage = (UINT)wParam;    // new ID (or 0)
  748.     m_nIDTracking = (UINT)wParam;       // so F1 on toolbar buttons work
  749.     return nIDLast;
  750. }
  751.  
  752. CWnd* CFrameWnd::GetMessageBar()
  753. {
  754.     return GetDescendantWindow(AFX_IDW_STATUS_BAR);
  755. }
  756.  
  757. void CFrameWnd::OnEnterIdle(UINT nWhy, CWnd* /*pWho*/)
  758. {
  759.     if (nWhy != MSGF_MENU || m_nIDTracking == m_nIDLastMessage)
  760.         return;
  761.  
  762.     OnSetMessageString(m_nIDTracking, NULL);    // set the message string
  763.     ASSERT(m_nIDTracking == m_nIDLastMessage);
  764. }
  765.  
  766. /////////////////////////////////////////////////////////////////////////////
  767. // CFrameWnd standard control bar management
  768.  
  769. void CFrameWnd::OnSysColorChange()
  770. {
  771.     afxData.UpdateSysColors();
  772.  
  773.     // Recolor the global brushes used by control bars
  774.     if (!(GetStyle() & WS_CHILD))
  775.         SendMessageToDescendants(WM_SYSCOLORCHANGE, 0, 0L);
  776. }
  777.  
  778. void CFrameWnd::OnUpdateControlBarMenu(CCmdUI* pCmdUI)
  779. {
  780.     ASSERT(ID_VIEW_STATUS_BAR == AFX_IDW_STATUS_BAR);
  781.     ASSERT(ID_VIEW_TOOLBAR == AFX_IDW_TOOLBAR);
  782.  
  783.     CWnd* pBar;
  784.     if ((pBar = GetDescendantWindow(pCmdUI->m_nID)) == NULL)
  785.     {
  786.         pCmdUI->ContinueRouting();
  787.         return; // not for us
  788.     }
  789.  
  790.     pCmdUI->SetCheck((pBar->GetStyle() & WS_VISIBLE) != 0);
  791. }
  792.  
  793. BOOL CFrameWnd::OnBarCheck(UINT nID)
  794. {
  795.     ASSERT(ID_VIEW_STATUS_BAR == AFX_IDW_STATUS_BAR);
  796.     ASSERT(ID_VIEW_TOOLBAR == AFX_IDW_TOOLBAR);
  797.  
  798.     CWnd* pBar;
  799.     if ((pBar = GetDescendantWindow(nID)) == NULL)
  800.         return FALSE;   // not for us
  801.  
  802.     // toggle visible state
  803.     pBar->ShowWindow((pBar->GetStyle() & WS_VISIBLE) == 0);
  804.     RecalcLayout();
  805.  
  806.     return TRUE;
  807. }
  808.  
  809. /////////////////////////////////////////////////////////////////////////////
  810. // Support for standard status bar
  811.  
  812. void CFrameWnd::OnUpdateKeyIndicator(CCmdUI* pCmdUI)
  813. {
  814.     UINT nVK;
  815.  
  816.     switch (pCmdUI->m_nID)
  817.     {
  818.     case ID_INDICATOR_CAPS:
  819.         nVK = VK_CAPITAL;
  820.         break;
  821.  
  822.     case ID_INDICATOR_NUM:
  823.         nVK = VK_NUMLOCK;
  824.         break;
  825.  
  826.     case ID_INDICATOR_SCRL:
  827.         nVK = VK_SCROLL;
  828.         break;
  829.  
  830.     default:
  831.         TRACE1("Warning: OnUpdateKeyIndicator - unknown indicator 0x%04X\n",
  832.             pCmdUI->m_nID);
  833.         pCmdUI->ContinueRouting();
  834.         return; // not for us
  835.     }
  836.  
  837.     pCmdUI->Enable(::GetKeyState(nVK) & 1);
  838.         // enable static text based on toggled key state
  839.     ASSERT(pCmdUI->m_bEnableChanged);
  840. }
  841.  
  842. /////////////////////////////////////////////////////////////////////////////
  843. // Setting title of frame window - UISG standard
  844.  
  845. void CFrameWnd::OnUpdateFrameTitle(BOOL bAddToTitle)
  846. {
  847.     if ((GetStyle() & FWS_ADDTOTITLE) == 0)
  848.         return;     // leave it alone!
  849.  
  850.     CDocument* pDocument = GetActiveDocument();
  851.     if (bAddToTitle && pDocument != NULL)
  852.         UpdateFrameTitleForDocument(pDocument->GetTitle());
  853.     else
  854.         UpdateFrameTitleForDocument(NULL);
  855. }
  856.  
  857. void CFrameWnd::UpdateFrameTitleForDocument(const char* pszDocName)
  858. {
  859.     char szText[256];
  860.     GetWindowText(szText, sizeof(szText));
  861.     char szOld[256];
  862.     lstrcpy(szOld, szText);     // used for compare if the same
  863.  
  864.     // keep the original title up to first '-'
  865.     LPSTR pchDash = _AfxStrChr(szText, '-');
  866.     LPSTR pchPrev;
  867.     if (pchDash != NULL && *(pchPrev = AnsiPrev(szText, pchDash)) == ' ')
  868.         pchDash = pchPrev;
  869.  
  870.     //  remove anything after "-" or " -"
  871.     if (pchDash != NULL)
  872.         *pchDash = '\0';
  873.  
  874.     // get name of currently active view
  875.     if (pszDocName != NULL)
  876.     {
  877.         lstrcat(szText, " - ");
  878.         lstrcat(szText, pszDocName);
  879.         // add current window # if needed
  880.         if (m_nWindow > 0)
  881.             wsprintf(szText + lstrlen(szText), ":%d", m_nWindow);
  882.     }
  883.  
  884.     // set title if changed, but don't remove completely
  885.             // NOTE: will be excessive for MDI Frame with maximized child
  886.     if (lstrcmp(szText, szOld) != 0)
  887.         SetWindowText(szText);
  888. }
  889.  
  890. /////////////////////////////////////////////////////////////////////////////
  891.  
  892. void CFrameWnd::OnSetPreviewMode(BOOL bPreview, CPrintPreviewState* pState)
  893. {
  894.     // default implementation changes control bars, menu and main pane window
  895.  
  896.     HWND hWnd;
  897.     // Set visibility of standard ControlBars (only the first 32)
  898.     DWORD dwOldStates = 0;
  899.     for (hWnd = ::GetTopWindow(m_hWnd); hWnd != NULL;
  900.                                 hWnd = ::GetNextWindow(hWnd, GW_HWNDNEXT))
  901.     {
  902.         UINT nID = _AfxGetDlgCtrlID(hWnd);
  903.         if (nID >= AFX_IDW_CONTROLBAR_FIRST &&
  904.             nID <= AFX_IDW_CONTROLBAR_FIRST + 31)
  905.         {
  906.             DWORD dwMask = 1L << (nID - AFX_IDW_CONTROLBAR_FIRST);
  907.             int cmdShow = (pState->dwStates & dwMask) == 0 ? SW_HIDE : SW_SHOW;
  908.             
  909.             if (::ShowWindow(hWnd, cmdShow))
  910.                 dwOldStates |= dwMask;      // save if previously visible
  911.         }
  912.     }
  913.     pState->dwStates = dwOldStates; // save for restore
  914.  
  915.     if (bPreview)
  916.     {
  917.         // Entering Print Preview
  918.  
  919.         ASSERT(m_lpfnCloseProc == NULL);    // no chaining
  920.         m_lpfnCloseProc = pState->lpfnCloseProc;
  921.  
  922.         // Get rid of the menu first (will resize the window)
  923.         pState->hMenu = ::GetMenu(m_hWnd);
  924.         if (pState->hMenu != NULL)
  925.         {
  926.             // Invalidate before SetMenu since we are going to replace
  927.             //  the frame's client area anyway
  928.             Invalidate();
  929.             SetMenu(NULL);
  930.         }
  931.  
  932.         // Save the accelerator table and remove it.
  933.         pState->hAccelTable = m_hAccelTable;
  934.         m_hAccelTable = NULL;
  935.  
  936.         // Hide the main pane
  937.         hWnd = ::GetDlgItem(m_hWnd, pState->nIDMainPane);
  938.         ASSERT(hWnd != NULL);       // must be one that we are hiding!
  939.         ::ShowWindow(hWnd, SW_HIDE);
  940.  
  941.         // Make room for the PreviewView by changing AFX_IDW_PANE_FIRST's ID
  942.         // to AFX_IDW_PREVIEW_FIRST
  943.         if (pState->nIDMainPane != AFX_IDW_PANE_FIRST)
  944.             hWnd = ::GetDlgItem(m_hWnd, AFX_IDW_PANE_FIRST);
  945.         if (hWnd != NULL)
  946.             _AfxSetDlgCtrlID(hWnd, AFX_IDW_PANE_SAVE);
  947.     
  948.         if ((::GetWindowLong(m_hWnd, GWL_STYLE) & (WS_HSCROLL|WS_VSCROLL)) != 0)
  949.         {
  950.             TRACE0("Warning: Scroll Bars in Frame Windows may cause"
  951.                 " unusual behaviour\n");
  952.         }
  953.     }
  954.     else
  955.     {
  956.         // Leaving Preview
  957.  
  958.         m_lpfnCloseProc = NULL;
  959.  
  960.         // shift original AFX_IDW_PANE_FIRST back to its rightful ID
  961.         hWnd = ::GetDlgItem(m_hWnd, AFX_IDW_PANE_SAVE);
  962.         if (hWnd != NULL)
  963.             _AfxSetDlgCtrlID(hWnd, AFX_IDW_PANE_FIRST);
  964.  
  965.         // now show main pane that was hidden
  966.         if (pState->nIDMainPane != AFX_IDW_PANE_FIRST)
  967.             hWnd = ::GetDlgItem(m_hWnd, pState->nIDMainPane);
  968.         ASSERT(hWnd != NULL);
  969.         ::ShowWindow(hWnd, SW_SHOW);
  970.  
  971.         // put the menu back in place if it was removed before
  972.         if (pState->hMenu != NULL)
  973.         {
  974.             // Invalidate before SetMenu since we are going to replace
  975.             //  the frame's client area anyway
  976.             Invalidate();
  977.             ::SetMenu(m_hWnd, pState->hMenu);
  978.         }
  979.  
  980.         // Restore the Accelerator table
  981.         m_hAccelTable = pState->hAccelTable;
  982.     }
  983. }
  984.  
  985. void CFrameWnd::RecalcLayout()
  986. {
  987.     // Under Windows 3.0 or Windows 3.1 in Win30 compatibility mode,
  988.     //  doing DeferWindowPos on multiple overlapping windows with
  989.     //  erase background will sometimes copy bad backgrounds, so
  990.     //  we force a repaint all the time
  991.     if (!afxData.bWin31 || afxData.bWin30Compat)
  992.         Invalidate();
  993.  
  994.     // reposition all the child windows (regardless of ID)
  995.     RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST);
  996. }
  997.  
  998. void CFrameWnd::OnSize(UINT nType, int cx, int cy)
  999. {
  1000.     CWnd::OnSize(nType, cx, cy);    // important for MDI Children
  1001.     if (nType != SIZE_MINIMIZED)
  1002.         RecalcLayout();
  1003. }
  1004.  
  1005. BOOL CFrameWnd::OnEraseBkgnd(CDC* pDC)
  1006. {
  1007.     if (m_pViewActive != NULL)
  1008.         return TRUE;        // active view will erase/paint itself
  1009.     // for view-less frame just use the default background fill
  1010.     return CWnd::OnEraseBkgnd(pDC);
  1011. }
  1012.  
  1013. void CFrameWnd::ActivateFrame(int nCmdShow)
  1014.     // nCmdShow is the normal show mode this frame should be in
  1015. {
  1016.     if (!IsWindowVisible())
  1017.         ShowWindow((nCmdShow == -1) ? SW_SHOW : nCmdShow); // show it
  1018.     else if (IsIconic())
  1019.         ShowWindow((nCmdShow == -1) ? SW_RESTORE : nCmdShow);
  1020.  
  1021.     BringWindowToTop();
  1022.     HWND hWndLastPop = ::GetLastActivePopup(m_hWnd);
  1023.     if (hWndLastPop != NULL && hWndLastPop != m_hWnd)
  1024.         ::BringWindowToTop(hWndLastPop);
  1025. }
  1026.  
  1027. /////////////////////////////////////////////////////////////////////////////
  1028. // CFrameWnd Diagnostics
  1029.  
  1030. #ifdef _DEBUG
  1031. void CFrameWnd::AssertValid() const
  1032. {
  1033.     CWnd::AssertValid();
  1034.     if (m_pViewActive != NULL)
  1035.         ASSERT_VALID(m_pViewActive);
  1036. }
  1037.  
  1038. void CFrameWnd::Dump(CDumpContext& dc) const
  1039. {
  1040.     CWnd::Dump(dc);
  1041.     AFX_DUMP1(dc, "\nm_hAccelTable = ", (UINT)m_hAccelTable);
  1042.     AFX_DUMP1(dc, "\nm_nWindow = ", m_nWindow);
  1043.     AFX_DUMP1(dc, "\nm_nIDHelp = ", m_nIDHelp);
  1044.     AFX_DUMP1(dc, "\nm_nIDTracking = ", m_nIDTracking);
  1045.     AFX_DUMP1(dc, "\nm_nIDLastMessage = ", m_nIDLastMessage);
  1046.     AFX_DUMP0(dc, "\nm_pViewActive = ");
  1047.     if (m_pViewActive)
  1048.         dc << m_pViewActive;
  1049.     else
  1050.         AFX_DUMP0(dc, "none");
  1051. }
  1052. #endif //_DEBUG
  1053.  
  1054. /////////////////////////////////////////////////////////////////////////////
  1055.