home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #ifdef AFX_OLE3_SEG
- #pragma code_seg(AFX_OLE3_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- /////////////////////////////////////////////////////////////////////////////
- // COleCntrFrameWnd implementation
-
- COleCntrFrameWnd::COleCntrFrameWnd(COleIPFrameWnd* pInPlaceFrame)
- {
- m_pInPlaceFrame = pInPlaceFrame;
- RemoveFrameWnd();
- }
-
- COleCntrFrameWnd::~COleCntrFrameWnd()
- {
- AddFrameWnd();
- Detach();
- }
-
- void COleCntrFrameWnd::RecalcLayout(BOOL /*bNotify*/)
- {
- if (!m_bInRecalcLayout)
- {
- m_bInRecalcLayout = TRUE;
- m_nIdleFlags &= ~(idleLayout|idleNotify);
-
- ASSERT_VALID(m_pInPlaceFrame);
- COleServerDoc* pDoc = (COleServerDoc*)m_pInPlaceFrame->GetActiveDocument();
- if (pDoc != NULL && AfxGetThread()->m_pActiveWnd == m_pInPlaceFrame)
- {
- ASSERT_VALID(pDoc);
- ASSERT_KINDOF(COleServerDoc, pDoc);
-
- if (this == m_pInPlaceFrame->m_pMainFrame)
- pDoc->OnResizeBorder(NULL, m_pInPlaceFrame->m_lpFrame, TRUE);
- if (this == m_pInPlaceFrame->m_pDocFrame)
- pDoc->OnResizeBorder(NULL, m_pInPlaceFrame->m_lpDocFrame, FALSE);
- }
- m_bInRecalcLayout = FALSE;
- }
- }
-
- void COleCntrFrameWnd::OnIdleUpdateCmdUI()
- {
- // do frame delayed recalc
- if (m_nIdleFlags & idleLayout)
- RecalcLayout(m_nIdleFlags & idleNotify);
-
- // update control bars
- POSITION pos = m_listControlBars.GetHeadPosition();
- while (pos != NULL)
- {
- CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
- ASSERT(pBar != NULL);
- ASSERT_VALID(pBar);
- AfxCallWndProc(pBar, pBar->m_hWnd, WM_IDLEUPDATECMDUI, TRUE, 0);
- }
- }
-
- BOOL COleCntrFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
- AFX_CMDHANDLERINFO* pHandlerInfo)
- {
- ASSERT_VALID(m_pInPlaceFrame);
-
- // pump through inplace frame
- CPushRoutingFrame push(this);
- return m_pInPlaceFrame->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
- }
-
- void COleCntrFrameWnd::PostNcDestroy()
- {
- // do nothing to avoid destroying window
- }
-
- #ifdef _DEBUG
- void COleCntrFrameWnd::AssertValid() const
- {
- // COleCntrFrameWnd bends the CWnd rules just a little bit.
-
- ASSERT(m_hWnd == NULL || ::IsWindow(m_hWnd));
- }
- #endif //_DEBUG
-
- /////////////////////////////////////////////////////////////////////////////
- // COleIPFrameWnd implementation
-
- BEGIN_MESSAGE_MAP(COleIPFrameWnd, CFrameWnd)
- //{{AFX_MSG_MAP(COleIPFrameWnd)
- ON_WM_SIZE()
- ON_MESSAGE(WM_RECALCPARENT, OnRecalcParent)
- ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
- ON_WM_WINDOWPOSCHANGING()
- ON_WM_CREATE()
- ON_WM_DESTROY()
- ON_MESSAGE(WM_SIZECHILD, OnResizeChild)
- ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString)
- ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateControlBarMenu)
- ON_COMMAND_EX(ID_VIEW_STATUS_BAR, OnBarCheck)
- ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLBAR, OnUpdateControlBarMenu)
- ON_COMMAND_EX(ID_VIEW_TOOLBAR, OnBarCheck)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- COleIPFrameWnd::COleIPFrameWnd()
- {
- // initialize OLEINPLACEFRAMEINFO struct
- memset(&m_frameInfo, 0, sizeof(m_frameInfo));
- m_frameInfo.cb = sizeof m_frameInfo;
-
- // initialize in-place state
- m_bUIActive = FALSE;
- m_lpFrame = NULL;
- m_lpDocFrame = NULL;
- m_hOleMenu = NULL;
- m_rectPos.SetRectEmpty();
- m_rectClip.SetRectEmpty();
- m_bInsideRecalc = FALSE;
- m_hSharedMenu = NULL;
- m_pMainFrame = NULL;
- m_pDocFrame = NULL;
- ASSERT_VALID(this);
- }
-
- COleIPFrameWnd::~COleIPFrameWnd()
- {
- ASSERT_VALID(this);
-
- // destroy wrappers of container's frames
- delete m_pMainFrame;
- delete m_pDocFrame;
-
- // destroy shared menu
- if (m_hSharedMenu != NULL)
- ::DestroyMenu(m_hSharedMenu);
-
- // interfaces to the container should already be released
- RELEASE(m_lpFrame);
- RELEASE(m_lpDocFrame);
- }
-
- int COleIPFrameWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- ASSERT_VALID(this);
-
- if (CFrameWnd::OnCreate(lpCreateStruct) < 0)
- return -1;
-
- // remove WS_EX_CLIENTEDGE style if present
- ModifyStyleEx(WS_EX_CLIENTEDGE, 0, 0);
-
- // need to remove the pending WM_SETMESSAGESTRING from the queue
- MSG msg;
- PeekMessage(&msg, m_hWnd, WM_SETMESSAGESTRING, WM_SETMESSAGESTRING,
- PM_REMOVE|PM_NOYIELD);
-
- ASSERT_VALID(this);
- return 0;
- }
-
- void COleIPFrameWnd::OnDestroy()
- {
- // notify the container that the rectangle has changed!
- COleServerDoc* pDoc = (COleServerDoc*)GetActiveDocument();
- if (pDoc != NULL)
- {
- ASSERT_KINDOF(COleServerDoc, pDoc);
-
- // close and abort changes to the document
- pDoc->DisconnectViews();
- pDoc->OnCloseDocument();
- }
-
- // explicitly destroy all of the dock bars since this window
- // is actually in the container and will not be destroyed
- if (m_pMainFrame != NULL)
- m_pMainFrame->DestroyDockBars();
- if (m_pDocFrame != NULL)
- m_pDocFrame->DestroyDockBars();
-
- CFrameWnd::OnDestroy();
- }
-
- BOOL COleIPFrameWnd::OnCreateControlBars(CWnd* pWndFrame, CWnd* /*pWndDoc*/)
- {
- ASSERT(pWndFrame != NULL);
- UNUSED(pWndFrame); // not used in release builds
-
- return TRUE;
- }
-
- BOOL COleIPFrameWnd::OnCreateControlBars(CFrameWnd* pWndFrame,
- CFrameWnd* pWndDoc)
- {
- return OnCreateControlBars((CWnd*)pWndFrame, (CWnd*)pWndDoc);
- }
-
- void COleIPFrameWnd::OnIdleUpdateCmdUI()
- {
- // update toolbars which may be on the container
- // and allow delayed recalc layouts to execute
- if (m_pMainFrame != NULL)
- m_pMainFrame->OnIdleUpdateCmdUI();
- if (m_pDocFrame != NULL)
- m_pDocFrame->OnIdleUpdateCmdUI();
- }
-
- void COleIPFrameWnd::OnWindowPosChanging(LPWINDOWPOS lpWndPos)
- {
- MSG msg;
- if (!::PeekMessage(&msg, NULL, WM_KICKIDLE, WM_KICKIDLE, PM_NOREMOVE))
- ::PostThreadMessage(GetCurrentThreadId(), WM_KICKIDLE, 0, 0);
-
- CFrameWnd::OnWindowPosChanging(lpWndPos);
- }
-
- LRESULT COleIPFrameWnd::OnSetMessageString(WPARAM wParam, LPARAM lParam)
- {
- USES_CONVERSION;
-
- if (m_lpFrame != NULL)
- {
- LPCTSTR lpsz = NULL;
- CString strMessage;
-
- // set the message bar text
- if (lParam != NULL)
- {
- ASSERT(wParam == 0); // can't have both an ID and a string
- lpsz = (LPCTSTR)lParam; // set an explicit string
- }
- else if (wParam != 0)
- {
- // get message associated with the ID indicated by wParam
- GetMessageString(wParam, strMessage);
- lpsz = strMessage;
- }
-
- // notify container of new status text
- if (lpsz == NULL)
- lpsz = _T("");
- m_lpFrame->SetStatusText(T2COLE(lpsz));
- }
-
- UINT nIDLast = m_nIDLastMessage;
- m_nIDLastMessage = (UINT)wParam; // new ID (or 0)
- m_nIDTracking = (UINT)wParam; // so F1 on toolbar buttons work
- return nIDLast;
- }
-
- BOOL COleIPFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
- CWnd* pParentWnd, CCreateContext* pContext)
- {
- if (pParentWnd != NULL)
- ASSERT_VALID(pParentWnd);
-
- // only do this once
- ASSERT_VALID_IDR(nIDResource);
- ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
-
- m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE)
-
- // create the window (use child window style create)
- CRect rect(0, 0, 0, 0);
- if (!CWnd::Create(NULL, NULL, dwDefaultStyle, rect, pParentWnd,
- nIDResource, pContext))
- {
- return FALSE; // will self destruct on failure normally
- }
-
- // load accelerator resource
- LoadAccelTable(MAKEINTRESOURCE(nIDResource));
-
- return TRUE;
- }
-
- void COleIPFrameWnd::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
- {
- // recalc layout is not called in OnSize since COleIPFrameWnd does
- // "inside out" recalc -- which is driven by the size of the
- // inner most window changing, not the outer most!
- }
-
- LRESULT COleIPFrameWnd::OnResizeChild(WPARAM, LPARAM lParam)
- {
- // notify the container that the rectangle has changed!
- COleServerDoc* pDoc = (COleServerDoc*)GetActiveDocument();
- if (pDoc == NULL)
- return 0;
-
- ASSERT_KINDOF(COleServerDoc, pDoc);
-
- // get new rect and parent
- CRect rectNew;
- rectNew.CopyRect((LPCRECT)lParam);
- CWnd* pParentWnd = GetParent();
- ASSERT_VALID(pParentWnd);
-
- // convert rectNew relative to pParentWnd
- ClientToScreen(&rectNew);
- pParentWnd->ScreenToClient(&rectNew);
-
- // adjust the new rectangle for the current control bars
- CWnd* pLeftOver = GetDlgItem(AFX_IDW_PANE_FIRST);
- ASSERT(pLeftOver != NULL);
- CRect rectCur = m_rectPos;
- pLeftOver->CalcWindowRect(&rectCur, CWnd::adjustOutside);
- rectNew.left += m_rectPos.left - rectCur.left;
- rectNew.top += m_rectPos.top - rectCur.top;
- rectNew.right -= rectCur.right - m_rectPos.right;
- rectNew.bottom -= rectCur.bottom - m_rectPos.bottom;
- OnRequestPositionChange(rectNew);
-
- return 0;
- }
-
- void COleIPFrameWnd::OnRequestPositionChange(LPCRECT lpRect)
- {
- COleServerDoc* pDoc = (COleServerDoc*)GetActiveDocument();
- ASSERT_VALID(pDoc);
- ASSERT_KINDOF(COleServerDoc, pDoc);
-
- // DocObjects don't need to generate OnPosRectChange calls,
- // so we can just return if this is a DoCobject
-
- if (pDoc->IsDocObject())
- return;
-
- // The default behavior is to not affect the extent during the
- // call to RequestPositionChange. This results in consistent
- // scaling behavior.
-
- pDoc->RequestPositionChange(lpRect);
- }
-
- LRESULT COleIPFrameWnd::OnRecalcParent(WPARAM, LPARAM lParam)
- {
- // simply call recalc layout
- RepositionFrame(&m_rectPos, &m_rectClip);
-
- // fill in the new rectangle if specified
- if ((LPRECT)lParam != NULL)
- *(LPRECT)lParam = m_rectPos;
-
- return TRUE;
- }
-
- void COleIPFrameWnd::RecalcLayout(BOOL /*bNotify*/)
- {
- ASSERT_VALID(this);
-
- // better have a parent window (only used for inplace)
- CWnd* pParentWnd = GetParent();
- ASSERT_VALID(pParentWnd);
-
- // see if this frame is supporting a normal in-place object or
- // a DocObject. DocObjects put scrollbars on the inside of the rect
-
- UINT nAdjustType = CWnd::adjustBorder;
- COleServerDoc* pDoc = (COleServerDoc*) GetActiveDocument();
- if (pDoc != NULL)
- {
- ASSERT_VALID(pDoc);
- if (pDoc->IsDocObject())
- nAdjustType = CWnd::adjustOutside;
- }
-
- // first call reposition bars with arbitarily large rect just to
- // see how much space the bars will take up
- CRect rectBig(0, 0, INT_MAX/2, INT_MAX/2);
- CRect rectLeft;
- RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,
- &rectLeft, &rectBig);
-
- // grow the rect by the size of the control bars
- CRect rect = m_rectPos;
- rect.left -= rectLeft.left;
- rect.top -= rectLeft.top;
- rect.right += INT_MAX/2 - rectLeft.right;
- rect.bottom += INT_MAX/2 - rectLeft.bottom;
-
- // see how much extra space for non-client areas (such as scrollbars)
- // that the view needs.
- CWnd* pLeftOver = GetDlgItem(AFX_IDW_PANE_FIRST);
- if (pLeftOver != NULL)
- {
- rectBig = m_rectPos;
- pLeftOver->CalcWindowRect(&rectBig, CWnd::adjustOutside);
- rect.left -= m_rectPos.left - rectBig.left;
- rect.top -= m_rectPos.top - rectBig.top;
- rect.right += rectBig.right - m_rectPos.right;
- rect.bottom += rectBig.bottom - m_rectPos.bottom;
- }
-
- // adjust for non-client area on the frame window
- CalcWindowRect(&rect, nAdjustType);
-
- // the frame window must be clipped to the visible part in the container
- CRect rectVis;
- rectVis.IntersectRect(&rect, &m_rectClip);
-
- // move the window
- AfxRepositionWindow(NULL, m_hWnd, &rectVis);
-
- // now resize the control bars relative to the (now moved) frame
- pParentWnd->ClientToScreen(&rect);
- ScreenToClient(&rect);
- RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST,
- CWnd::reposDefault, NULL, &rect);
- }
-
- void COleIPFrameWnd::RepositionFrame(LPCRECT lpPosRect, LPCRECT lpClipRect)
- {
- ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
- ASSERT(AfxIsValidAddress(lpClipRect, sizeof(RECT), FALSE));
-
- // gaurd against recursion
- if (m_bInsideRecalc)
- return;
- m_bInsideRecalc = TRUE;
-
- // remember the client area for later
- m_rectPos.CopyRect(lpPosRect);
- m_rectClip.CopyRect(lpClipRect);
-
- // recalc layout based on new position & clipping rectangles
- RecalcLayout();
-
- // remove recursion lockout
- m_bInsideRecalc = FALSE;
- }
-
- BOOL COleIPFrameWnd::PreTranslateMessage(MSG* pMsg)
- {
- // check server's accelerators first
- if (CFrameWnd::PreTranslateMessage(pMsg))
- return TRUE;
-
- if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
- {
- // always check to see if they exist in the default accel table
- // (they may exist but not be translated when disabled)
- HACCEL hAccel = GetDefaultAccelerator();
- if (hAccel != NULL && IsAccelerator(hAccel,
- CopyAcceleratorTable(hAccel, NULL, 0), pMsg, NULL))
- {
- return TRUE;
- }
-
- // check container's accelerators as last chance
- OLEINPLACEFRAMEINFO frameInfo = m_frameInfo;
- if (::OleTranslateAccelerator(m_lpFrame, &frameInfo, pMsg) == S_OK)
- return TRUE;
- }
-
- return FALSE; // keystroke not processed.
- }
-
- void COleIPFrameWnd::OnUpdateControlBarMenu(CCmdUI* pCmdUI)
- {
- if (GetControlBar(pCmdUI->m_nID) != NULL)
- CFrameWnd::OnUpdateControlBarMenu(pCmdUI);
- else if (m_pMainFrame != NULL &&
- m_pMainFrame->GetControlBar(pCmdUI->m_nID) != NULL)
- {
- m_pMainFrame->OnUpdateControlBarMenu(pCmdUI);
- }
- else if (m_pDocFrame != NULL &&
- m_pDocFrame->GetControlBar(pCmdUI->m_nID) != NULL)
- {
- m_pDocFrame->OnUpdateControlBarMenu(pCmdUI);
- }
- else
- pCmdUI->ContinueRouting();
- }
-
- BOOL COleIPFrameWnd::OnBarCheck(UINT nID)
- {
- if (GetControlBar(nID) != NULL)
- return CFrameWnd::OnBarCheck(nID);
- else if (m_pMainFrame != NULL && m_pMainFrame->GetControlBar(nID) != NULL)
- return m_pMainFrame->OnBarCheck(nID);
- else if (m_pDocFrame != NULL && m_pDocFrame->GetControlBar(nID) != NULL)
- return m_pDocFrame->OnBarCheck(nID);
- return FALSE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Special-case context sensitive help
-
- void COleIPFrameWnd::OnContextHelp()
- {
- if (m_bHelpMode == HELP_ACTIVE || !CanEnterHelpMode())
- return;
-
- // notify container that we are entering context sensitive help
- BOOL bHelpMode = m_bHelpMode;
- m_bHelpMode = HELP_ACTIVE;
- ASSERT(m_lpFrame != NULL);
- if (m_lpFrame->ContextSensitiveHelp(TRUE) != S_OK ||
- (m_lpDocFrame != NULL && m_lpDocFrame->ContextSensitiveHelp(TRUE) != S_OK))
- {
- m_bHelpMode = HELP_INACTIVE;
- return;
- }
- m_bHelpMode = bHelpMode;
-
- // echo help mode to top-level frame
- CFrameWnd* pFrameWnd = GetTopLevelFrame();
- if (pFrameWnd != this)
- pFrameWnd->m_bHelpMode = HELP_ACTIVE;
-
- // now enter context sensitive help mode ourselves
- CFrameWnd::OnContextHelp();
-
- // echo help mode to top-level frame
- if (pFrameWnd != this)
- pFrameWnd->m_bHelpMode = m_bHelpMode;
-
- if (m_bHelpMode == HELP_INACTIVE)
- {
- // make sure container exits context sensitive help mode
- m_lpFrame->ContextSensitiveHelp(FALSE);
- if (m_lpDocFrame != NULL)
- m_lpDocFrame->ContextSensitiveHelp(FALSE);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // In-place activation startup
-
- HMENU COleIPFrameWnd::GetInPlaceMenu()
- {
- // get active document associated with this frame window
- CDocument* pDoc = GetActiveDocument();
- ASSERT_VALID(pDoc);
-
- // get in-place menu from the doc template
- CDocTemplate* pTemplate = pDoc->GetDocTemplate();
- ASSERT_VALID(pTemplate);
- return pTemplate->m_hMenuInPlaceServer;
- }
-
- BOOL COleIPFrameWnd::BuildSharedMenu()
- {
- HMENU hMenu = GetInPlaceMenu();
-
- // create shared menu
- ASSERT(m_hSharedMenu == NULL);
- if ((m_hSharedMenu = ::CreateMenu()) == NULL)
- return FALSE;
-
- // start out by getting menu from container
- memset(&m_menuWidths, 0, sizeof m_menuWidths);
- if (m_lpFrame->InsertMenus(m_hSharedMenu, &m_menuWidths) != S_OK)
- {
- ::DestroyMenu(m_hSharedMenu);
- m_hSharedMenu = NULL;
- return FALSE;
- }
- // container shouldn't touch these
- ASSERT(m_menuWidths.width[1] == 0);
- ASSERT(m_menuWidths.width[3] == 0);
- ASSERT(m_menuWidths.width[5] == 0);
-
- // only copy the popups if there is a menu loaded
- if (hMenu == NULL)
- return TRUE;
-
- // insert our menu popups amongst the container menus
- AfxMergeMenus(m_hSharedMenu, hMenu, &m_menuWidths.width[0], 1);
-
- // finally create the special OLE menu descriptor
- m_hOleMenu = ::OleCreateMenuDescriptor(m_hSharedMenu, &m_menuWidths);
-
- return m_hOleMenu != NULL;
- }
-
- void COleIPFrameWnd::DestroySharedMenu()
- {
- if (m_hSharedMenu == NULL)
- {
- ASSERT(m_hOleMenu == NULL);
- return;
- }
-
- // get in-place menu to be unmerged (must be same as during activation)
- HMENU hMenu = GetInPlaceMenu();
- if (hMenu == NULL)
- return;
-
- // remove our menu popups from the shared menu
- AfxUnmergeMenus(m_hSharedMenu, hMenu);
-
- // allow container to remove its items from the menu
- ASSERT(m_lpFrame != NULL);
- VERIFY(m_lpFrame->RemoveMenus(m_hSharedMenu) == S_OK);
-
- // now destroy the menu
- ::DestroyMenu(m_hSharedMenu);
- m_hSharedMenu = NULL;
-
- if (m_hOleMenu != NULL)
- {
- VERIFY(::OleDestroyMenuDescriptor(m_hOleMenu) == S_OK);
- m_hOleMenu = NULL;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleIPFrameWnd diagnostics
-
- #ifdef _DEBUG
- void COleIPFrameWnd::AssertValid() const
- {
- CFrameWnd::AssertValid();
- if (m_hSharedMenu != NULL)
- ASSERT(::IsMenu(m_hSharedMenu));
- }
-
- void COleIPFrameWnd::Dump(CDumpContext& dc) const
- {
- CFrameWnd::Dump(dc);
-
- dc << "m_lpFrame = " << m_lpFrame;
- dc << "\nm_lpDocFrame = " << m_lpDocFrame;
- dc << "\nm_hOleMenu = " << m_hOleMenu;
- dc << "\nm_rectPos = " << m_rectPos;
- dc << "\nm_rectClip = " << m_rectClip;
- dc << "\nm_bInsideRecalc = " << m_bInsideRecalc;
- dc << "\nm_hSharedMenu = " << m_hSharedMenu;
-
- dc << "\n";
- }
- #endif //_DEBUG
-
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
-
- IMPLEMENT_DYNCREATE(COleIPFrameWnd, CFrameWnd)
-
- /////////////////////////////////////////////////////////////////////////////
-