Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1432 lines
34 KiB

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1995 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 _MAC
#include <macname1.h>
#include <Processes.h>
#include <macname2.h>
#endif
#ifdef AFX_OLE2_SEG
#pragma code_seg(AFX_OLE2_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// COleFrameHook Construction & Destruction
COleFrameHook::COleFrameHook(CFrameWnd* pFrameWnd, COleClientItem* pItem)
{
ASSERT_VALID(pItem);
ASSERT_VALID(pFrameWnd);
m_lpActiveObject = NULL;
m_pActiveItem = pItem;
m_pFrameWnd = pFrameWnd;
m_hWnd = pFrameWnd->m_hWnd;
m_bToolBarHidden = FALSE;
m_hAccelTable = NULL;
m_bInModalState = FALSE;
m_nModelessCount = 0;
pFrameWnd->m_pNotifyHook = this; // assume start out hooked
ASSERT_VALID(this);
}
COleFrameHook::~COleFrameHook()
{
if (m_pFrameWnd != NULL)
{
ASSERT_VALID(m_pFrameWnd);
if (m_pFrameWnd->m_pNotifyHook == this)
m_pFrameWnd->m_pNotifyHook = NULL;
}
ASSERT_VALID(this);
}
/////////////////////////////////////////////////////////////////////////////
// COleFrameHook overrides
void COleFrameHook::OnRecalcLayout()
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL)
return;
// get current border size (without current server control bars)
RECT rectBorder;
m_pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderGet, &rectBorder);
// allow server to resize/move its control bars
m_lpActiveObject->ResizeBorder(&rectBorder, &m_xOleInPlaceFrame,
m_pActiveItem->m_pInPlaceFrame == this);
}
BOOL COleFrameHook::OnDocActivate(BOOL bActive)
{
ASSERT_VALID(this);
#ifndef _MAC
if (m_lpActiveObject == NULL)
return TRUE;
// allow server to do document activation related actions
m_lpActiveObject->OnDocWindowActivate(bActive);
// make sure window caption gets updated later
COleFrameHook* pNotifyHook = m_pActiveItem->m_pInPlaceFrame;
pNotifyHook->m_pFrameWnd->DelayUpdateFrameTitle();
if (!bActive)
{
// clear border space
pNotifyHook->m_xOleInPlaceFrame.SetBorderSpace(NULL);
if (m_pActiveItem->m_pInPlaceDoc != NULL)
m_pActiveItem->m_pInPlaceDoc->m_xOleInPlaceFrame.SetBorderSpace(NULL);
// remove the menu hook when the doc is not active
pNotifyHook->m_xOleInPlaceFrame.SetMenu(NULL, NULL, NULL);
// unhook top-level frame if not needed
if (pNotifyHook != this)
{
// shouldn't be removing some other hook
ASSERT(pNotifyHook->m_pFrameWnd->m_pNotifyHook == pNotifyHook);
pNotifyHook->m_pFrameWnd->m_pNotifyHook = NULL;
}
}
else
{
// rehook top-level frame if necessary (no effect if top-level == doc-level)
pNotifyHook->m_pFrameWnd->m_pNotifyHook = pNotifyHook;
}
// don't do default if activating
return bActive;
#else // _MAC
if ((!bActive) && (m_pActiveItem != NULL))
{
ProcessSerialNumber psn;
m_pActiveItem->Deactivate();
psn.highLongOfPSN = 0;
psn.lowLongOfPSN = kCurrentProcess;
SetFrontProcess(&psn);
}
return TRUE;
#endif // _MAC
}
BOOL COleFrameHook::OnContextHelp(BOOL bEnter)
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return TRUE;
// allow all servers to enter/exit context sensitive help mode
return NotifyAllInPlace(bEnter, &COleFrameHook::DoContextSensitiveHelp);
}
/////////////////////////////////////////////////////////////////////////////
// COleFrameHook callbacks for the top-level frame
BOOL COleFrameHook::OnPreTranslateMessage(MSG* pMsg)
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return FALSE;
// allow server to translate accelerators
if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
return m_lpActiveObject->TranslateAccelerator(pMsg) == S_OK;
return FALSE;
}
void COleFrameHook::OnActivate(BOOL bActive)
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return;
#ifdef _MAC
if(bActive)
{
afxData.bOleIgnoreSuspend = TRUE;
}
#endif
if (m_pFrameWnd->IsWindowEnabled())
{
// allow active server to do frame level activation
m_lpActiveObject->OnFrameWindowActivate(bActive);
}
}
void COleFrameHook::OnEnableModeless(BOOL bEnable)
{
ASSERT_VALID(this);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return;
// allow server to disable/enable modeless dialogs
NotifyAllInPlace(bEnable, &COleFrameHook::DoEnableModeless);
}
BOOL COleFrameHook::OnUpdateFrameTitle()
{
ASSERT_VALID(this);
ASSERT_VALID(m_pActiveItem);
if (m_lpActiveObject == NULL || m_pActiveItem->m_pInPlaceFrame != this)
return FALSE;
return m_pActiveItem->OnUpdateFrameTitle();
}
void COleFrameHook::OnPaletteChanged(CWnd* pFocusWnd)
{
CWnd* pWnd = m_pActiveItem->GetInPlaceWindow();
if (pWnd != NULL)
pWnd->SendMessage(WM_PALETTECHANGED, (WPARAM)pFocusWnd->GetSafeHwnd());
}
BOOL COleFrameHook::OnQueryNewPalette()
{
CWnd* pWnd = m_pActiveItem->GetInPlaceWindow();
if (pWnd != NULL)
return pWnd->SendMessage(WM_QUERYNEWPALETTE);
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Helpers for notifications that have to affect all in-place windows
BOOL COleFrameHook::NotifyAllInPlace(
BOOL bParam, BOOL (COleFrameHook::*pNotifyFunc)(BOOL bParam))
{
ASSERT_VALID(this);
HWND hWndFrame = m_hWnd;
CWinApp* pApp = AfxGetApp();
// no doc manager - no templates
if (pApp->m_pDocManager == NULL)
return TRUE;
// walk all templates in the application
CDocTemplate* pTemplate;
POSITION pos = pApp->m_pDocManager->GetFirstDocTemplatePosition();
while (pos != NULL)
{
pTemplate = pApp->m_pDocManager->GetNextDocTemplate(pos);
ASSERT_VALID(pTemplate);
ASSERT_KINDOF(CDocTemplate, pTemplate);
// walk all documents in the template
POSITION pos2 = pTemplate->GetFirstDocPosition();
while (pos2)
{
COleDocument* pDoc = (COleDocument*)pTemplate->GetNextDoc(pos2);
ASSERT_VALID(pDoc);
if (pDoc->IsKindOf(RUNTIME_CLASS(COleDocument)))
{
// walk all COleClientItem objects in the document
COleClientItem* pItem;
POSITION pos3 = pDoc->GetStartPosition();
while ((pItem = pDoc->GetNextClientItem(pos3)) != NULL)
{
if (pItem->m_pInPlaceFrame != NULL &&
pItem->m_pInPlaceFrame->m_lpActiveObject != NULL &&
pItem->m_pView != NULL &&
AfxIsDescendant(hWndFrame, pItem->m_pView->m_hWnd))
{
// Whew! Found an in-place active item that is
// part of this frame window hierarchy.
COleFrameHook* pNotifyHook = pItem->m_pInPlaceFrame;
if (!(pNotifyHook->*pNotifyFunc)(bParam))
return FALSE;
}
}
}
}
}
return TRUE;
}
BOOL COleFrameHook::DoContextSensitiveHelp(BOOL bEnter)
{
ASSERT_VALID(this);
ASSERT(m_lpActiveObject != NULL);
return !FAILED(m_lpActiveObject->ContextSensitiveHelp(bEnter));
}
BOOL COleFrameHook::DoEnableModeless(BOOL bEnable)
{
ASSERT_VALID(this);
ASSERT(m_lpActiveObject != NULL);
// allow server to enable/disable any modeless windows
if (!bEnable)
{
if (m_nModelessCount++ == 0)
m_lpActiveObject->EnableModeless(FALSE);
}
else
{
if (m_nModelessCount != 0 && --m_nModelessCount == 0)
m_lpActiveObject->EnableModeless(TRUE);
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// COleClientItem - default in-place activation implementation
BOOL COleClientItem::CanActivate()
{
// don't allow in-place activations with iconic aspect items
if (m_nDrawAspect == DVASPECT_ICON)
return FALSE;
// if no view has been set, attempt to find suitable one.
// (necessary to get links to embeddings to work correctly)
if (m_pView == NULL)
{
// only use pActivateView if this item is in same document
_AFX_OLE_STATE* pOleState = _afxOleState;
if (pOleState->m_pActivateView != NULL &&
pOleState->m_pActivateView->GetDocument() != GetDocument())
{
pOleState->m_pActivateView = NULL; // not in same document
}
CView* pView = pOleState->m_pActivateView;
if (pView == NULL)
{
// no routing view available - just use first one
COleDocument* pDoc = GetDocument();
POSITION pos = pDoc->GetFirstViewPosition();
pView = pDoc->GetNextView(pos);
}
m_pView = pView;
}
return m_pView->GetSafeHwnd() != NULL;
}
void COleClientItem::OnActivate()
{
ASSERT_VALID(this);
// it is necessary to lock the object when it is in-place
// (without this, a link to an embedding may disconnect unexpectedly)
if (!m_bLocked)
{
OleLockRunning(m_lpObject, TRUE, FALSE);
m_bLocked = TRUE;
}
// notify the item of the state change
if (m_nItemState != activeState)
{
OnChange(OLE_CHANGED_STATE, (DWORD)activeState);
m_nItemState = activeState;
}
}
void COleClientItem::OnActivateUI()
{
ASSERT_VALID(this);
// notify the item of the state change
if (m_nItemState != activeUIState)
{
OnChange(OLE_CHANGED_STATE, (DWORD)activeUIState);
m_nItemState = activeUIState;
}
// the container window must have WS_CLIPCHILDREN set
ASSERT_VALID(m_pView);
m_dwContainerStyle = m_pView->GetStyle();
m_pView->ModifyStyle(0, WS_CLIPCHILDREN);
// cache the server's HWND for later
LPOLEINPLACEOBJECT lpInPlaceObject =
QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
ASSERT(lpInPlaceObject != NULL);
// get the HWND for the in-place active object
HWND hWnd;
if (lpInPlaceObject->GetWindow(&hWnd) != S_OK)
hWnd = NULL;
lpInPlaceObject->Release();
m_hWndServer = hWnd;
// make sure top-level frame is hooked
if (m_pInPlaceFrame != NULL)
{
ASSERT_VALID(m_pInPlaceFrame->m_pFrameWnd);
m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook = m_pInPlaceFrame;
}
// make sure doc-level frame is hooked
if (m_pInPlaceDoc != NULL)
{
ASSERT_VALID(m_pInPlaceDoc->m_pFrameWnd);
m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook = m_pInPlaceDoc;
}
}
BOOL COleClientItem::OnShowControlBars(CFrameWnd* pFrameWnd, BOOL bShow)
{
ASSERT_VALID(pFrameWnd);
ASSERT_VALID(this);
// show/hide all bars marked with CBRS_HIDE_INPLACE style
BOOL bResult = FALSE;
if (bShow)
{
POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
while (pos)
{
CControlBar* pBar =
(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
ASSERT_VALID(pBar);
if ((pBar->GetBarStyle() & CBRS_HIDE_INPLACE) &&
(pBar->m_nStateFlags & CControlBar::tempHide))
{
pBar->m_nStateFlags &= ~CControlBar::tempHide;
pFrameWnd->ShowControlBar(pBar, TRUE, TRUE);
bResult = TRUE;
}
}
}
else
{
POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
while (pos)
{
CControlBar* pBar =
(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
ASSERT_VALID(pBar);
if (pBar->IsVisible() && (pBar->GetBarStyle() & CBRS_HIDE_INPLACE))
{
pBar->m_nStateFlags |= CControlBar::tempHide;
pFrameWnd->ShowControlBar(pBar, FALSE, TRUE);
bResult = TRUE;
}
}
}
return bResult;
}
BOOL COleClientItem::OnGetWindowContext(
CFrameWnd** ppMainFrame, CFrameWnd** ppDocFrame,
LPOLEINPLACEFRAMEINFO pFrameInfo)
{
ASSERT(AfxIsValidAddress(ppMainFrame, sizeof(CFrameWnd*)));
ASSERT(AfxIsValidAddress(ppDocFrame, sizeof(CFrameWnd*)));
ASSERT(pFrameInfo == NULL ||
AfxIsValidAddress(pFrameInfo, sizeof(OLEINPLACEFRAMEINFO)));
ASSERT_VALID(this);
ASSERT_VALID(m_pView);
// get main window of application
*ppMainFrame = m_pView->GetTopLevelFrame();
ASSERT_VALID(*ppMainFrame);
ASSERT_KINDOF(CFrameWnd, *ppMainFrame);
// get document window (if there is one)
CFrameWnd* pDocFrame = m_pView->GetParentFrame();
if (pDocFrame != *ppMainFrame)
{
*ppDocFrame = pDocFrame;
ASSERT_VALID(*ppDocFrame);
ASSERT_KINDOF(CFrameWnd, *ppDocFrame);
}
if (pFrameInfo != NULL)
{
// get accelerator table
CDocTemplate* pTemplate = GetDocument()->GetDocTemplate();
HACCEL hAccel = pTemplate != NULL ? pTemplate->m_hAccelInPlace : NULL;
pFrameInfo->cAccelEntries =
hAccel != NULL ? CopyAcceleratorTable(hAccel, NULL, 0) : 0;
pFrameInfo->haccel = pFrameInfo->cAccelEntries != 0 ? hAccel : NULL;
pFrameInfo->hwndFrame = (*ppMainFrame)->m_hWnd;
pFrameInfo->fMDIApp = *ppDocFrame != NULL;
}
return TRUE;
}
BOOL COleClientItem::OnScrollBy(CSize sizeExtent)
{
ASSERT_VALID(this);
ASSERT_VALID(m_pView);
// scroll through splitter or view
CSplitterWnd* pSplitter = CView::GetParentSplitter(m_pView, FALSE);
BOOL bResult;
if (pSplitter != NULL)
bResult = pSplitter->DoScrollBy(m_pView, sizeExtent);
else
bResult = m_pView->OnScrollBy(sizeExtent);
return bResult;
}
void COleClientItem::OnDeactivateUI(BOOL /*bUndoable*/)
{
ASSERT_VALID(this);
// notify the item of the state change
if (m_nItemState != activeState)
{
OnChange(OLE_CHANGED_STATE, (DWORD)activeState);
m_nItemState = activeState;
}
if (m_pView != NULL && m_pDocument->GetFirstViewPosition())
{
// restore container window's WS_CLIPCHILDREN bit...
ASSERT_VALID(m_pView);
m_pView->ModifyStyle(WS_CLIPCHILDREN, m_dwContainerStyle & WS_CLIPCHILDREN);
}
// restore original user interface on the frame window
CFrameWnd* pMainFrame;
CFrameWnd* pDocFrame = NULL;
if (OnGetWindowContext(&pMainFrame, &pDocFrame, NULL))
{
ASSERT_VALID(pMainFrame);
pMainFrame->DelayUpdateFrameTitle();
if (pMainFrame->NegotiateBorderSpace(CFrameWnd::borderSet, NULL))
pMainFrame->DelayRecalcLayout();
// restore original user interface on the document window
if (pDocFrame != NULL)
{
pDocFrame->DelayUpdateFrameTitle();
if (pDocFrame->NegotiateBorderSpace(CFrameWnd::borderSet, NULL))
pDocFrame->DelayRecalcLayout();
}
}
// cleanup frame interfaces allocated in GetWindowContext
if (m_pInPlaceFrame != NULL)
{
OnShowControlBars(m_pInPlaceFrame->m_pFrameWnd, TRUE);
#ifndef _MAC
// release OLE frame window hooks and allow menu update
::OleSetMenuDescriptor(NULL, m_pInPlaceFrame->m_pFrameWnd->m_hWnd,
NULL, NULL, NULL);
if (m_pInPlaceDoc != NULL)
{
::OleSetMenuDescriptor(NULL, m_pInPlaceDoc->m_pFrameWnd->m_hWnd,
NULL, NULL, NULL);
}
#endif
m_pInPlaceFrame->m_pFrameWnd->DelayUpdateFrameMenu(NULL);
// unhook from frame window
if (m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook == m_pInPlaceFrame)
m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook = NULL;
// cleanup document interfaces allocated in GetWindowContext
if (m_pInPlaceDoc != NULL)
{
OnShowControlBars(m_pInPlaceDoc->m_pFrameWnd, TRUE);
// unhook from frame window
if (m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook == m_pInPlaceDoc)
m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook = NULL;
}
}
// reset server HWND -- no longer necessary
m_hWndServer = NULL;
CWnd* pWnd = AfxGetMainWnd();
if (pWnd != NULL)
{
// set focus back to the container
pWnd = pWnd->GetTopLevelParent();
ASSERT_VALID(pWnd);
if (::GetActiveWindow() == pWnd->m_hWnd)
pWnd->SetFocus();
}
}
void COleClientItem::OnDeactivate()
{
ASSERT_VALID(this);
// notify the item of the state change
if (m_nItemState != loadedState)
{
OnChange(OLE_CHANGED_STATE, (DWORD)loadedState);
m_nItemState = loadedState;
}
// cleanup frame interfaces allocated in GetWindowContext
if (m_pInPlaceFrame != NULL)
{
// release in place frame
if (m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook == m_pInPlaceFrame)
m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook = NULL;
m_pInPlaceFrame->InternalRelease();
m_pInPlaceFrame = NULL;
// cleanup document interfaces allocated in GetWindowContext
if (m_pInPlaceDoc != NULL)
{
// release in place document
if (m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook == m_pInPlaceDoc)
m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook = NULL;
m_pInPlaceDoc->InternalRelease();
m_pInPlaceDoc = NULL;
}
}
// both frame-level and doc-level interfaces should be cleaned up
ASSERT(m_pInPlaceFrame == NULL);
ASSERT(m_pInPlaceDoc == NULL);
// no longer need the container window
m_pView = NULL;
}
void COleClientItem::OnDiscardUndoState()
{
ASSERT_VALID(this);
// default does nothing
}
void COleClientItem::OnDeactivateAndUndo()
{
ASSERT_VALID(this);
DeactivateUI(); // default is to UI deactivate
}
BOOL COleClientItem::OnChangeItemPosition(const CRect& rectPos)
{
if (!IsInPlaceActive())
return FALSE;
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(&rectPos, sizeof(CRect), FALSE));
ASSERT_VALID(m_pView);
// determine the visible rect based on intersection between client rect
CRect clipRect;
OnGetClipRect(clipRect);
CRect visRect;
visRect.IntersectRect(clipRect, rectPos);
// advise the server of the new visible rectangle
if (!visRect.IsRectEmpty())
return SetItemRects(&rectPos, &clipRect);
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// IOleInPlaceFrame notifications (default implementation)
void COleClientItem::OnInsertMenus(CMenu* pMenuShared,
LPOLEMENUGROUPWIDTHS lpMenuWidths)
{
ASSERT_VALID(this);
ASSERT_VALID(pMenuShared);
ASSERT(AfxIsValidAddress(lpMenuWidths, sizeof(OLEMENUGROUPWIDTHS)));
// initialize the group widths array
lpMenuWidths->width[0] = 0;
lpMenuWidths->width[2] = 0;
lpMenuWidths->width[4] = 0;
// get menu from document template
CDocTemplate* pTemplate = GetDocument()->GetDocTemplate();
HMENU hMenuOLE = pTemplate->m_hMenuInPlace;
// only copy the popups if there is a menu loaded
if (hMenuOLE == NULL)
return;
// insert our menu items and adjust group widths array
AfxMergeMenus(pMenuShared->GetSafeHmenu(), hMenuOLE, &lpMenuWidths->width[0], 0);
}
void COleClientItem::OnSetMenu(CMenu* pMenuShared, HOLEMENU holemenu,
HWND hwndActiveObject)
{
ASSERT_VALID(this);
ASSERT(m_pInPlaceFrame != NULL);
ASSERT(m_pInPlaceFrame->m_pFrameWnd != NULL);
// don't set the doc is active
CFrameWnd* pFrameWnd = m_pInPlaceFrame->m_pFrameWnd;
ASSERT_VALID(pFrameWnd);
if (m_pInPlaceDoc != NULL &&
m_pInPlaceDoc->m_pFrameWnd != pFrameWnd->GetActiveFrame())
{
return;
}
// update the menu
pFrameWnd->DelayUpdateFrameMenu(pMenuShared->GetSafeHmenu());
#ifndef _MAC
// enable/disable the OLE command routing hook
::OleSetMenuDescriptor(holemenu, pFrameWnd->m_hWnd,
hwndActiveObject, NULL, NULL);
if (m_pInPlaceDoc != NULL)
{
pFrameWnd = m_pInPlaceDoc->m_pFrameWnd;
ASSERT_VALID(pFrameWnd);
::OleSetMenuDescriptor(holemenu, pFrameWnd->m_hWnd,
hwndActiveObject, NULL, NULL);
}
#else
holemenu;
hwndActiveObject;
#endif
}
void COleClientItem::OnRemoveMenus(CMenu* pMenuShared)
{
ASSERT_VALID(this);
ASSERT_VALID(pMenuShared);
// get menu from document template
CDocTemplate* pTemplate = GetDocument()->GetDocTemplate();
HMENU hMenuOLE = pTemplate->m_hMenuInPlace;
if (hMenuOLE == NULL)
return;
// remove any menu popups originally added in OnInsertMenus
AfxUnmergeMenus(pMenuShared->GetSafeHmenu(), hMenuOLE);
}
BOOL COleClientItem::OnUpdateFrameTitle()
{
ASSERT_VALID(this);
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// In-place Activation operations
void COleClientItem::Deactivate()
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
ASSERT(IsInPlaceActive());
// get IOleInPlaceObject interface
LPOLEINPLACEOBJECT lpInPlaceObject =
QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
if (lpInPlaceObject == NULL)
{
Close(); // handle rare failure cases by calling Close
return;
}
// call IOleInPlaceObject::InPlaceDeactivate
m_scLast = lpInPlaceObject->InPlaceDeactivate();
lpInPlaceObject->Release();
if (FAILED(m_scLast))
{
Close(); // handle rare failure cases by calling Close
return;
}
m_nItemState = loadedState; // just in case server has crashed
}
void COleClientItem::DeactivateUI()
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
ASSERT(GetItemState() == activeUIState);
// get IOleInPlaceObject interface
LPOLEINPLACEOBJECT lpInPlaceObject =
QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
if (lpInPlaceObject == NULL)
{
Close(); // handle rare failure cases by calling Close
return;
}
// call IOleInPlaceObject::UIDeactivate
m_scLast = lpInPlaceObject->UIDeactivate();
lpInPlaceObject->Release();
if (FAILED(m_scLast))
{
Close(); // handle rare failure cases by calling Close
return;
}
m_nItemState = activeState; // just in case server has crashed
}
BOOL COleClientItem::SetItemRects(LPCRECT lpPosRect, LPCRECT lpClipRect)
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
ASSERT(IsInPlaceActive());
ASSERT(lpPosRect == NULL ||
AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
ASSERT(lpClipRect == NULL ||
AfxIsValidAddress(lpClipRect, sizeof(RECT), FALSE));
// get IOleInPlaceObject interface
LPOLEINPLACEOBJECT lpInPlaceObject =
QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
if (lpInPlaceObject == NULL)
return FALSE; // perhaps server crashed?
// use OnGetPosRect if rectangle not specified
CRect rectPos;
if (lpPosRect == NULL)
{
ASSERT(lpClipRect == NULL);
OnGetItemPosition(rectPos);
lpPosRect = &rectPos;
}
// use OnGetClipRect if clipping rectangle not specified
CRect rectClip;
if (lpClipRect == NULL)
{
OnGetClipRect(rectClip);
lpClipRect = &rectClip;
}
ASSERT(lpPosRect != NULL);
ASSERT(lpClipRect != NULL);
// notify the server of the new item rectangles
m_scLast = lpInPlaceObject->SetObjectRects(lpPosRect, lpClipRect);
lpInPlaceObject->Release();
// remember position rectangle as cached position
return !FAILED(m_scLast);
}
BOOL COleClientItem::ReactivateAndUndo()
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
ASSERT(IsInPlaceActive());
// get IOleInPlaceObject interface
LPOLEINPLACEOBJECT lpInPlaceObject =
QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
if (lpInPlaceObject == NULL)
{
Close(); // handle rare failure cases by calling Close
return FALSE;
}
// call IOleInPlaceObject::ReactivateAndUndo
m_scLast = lpInPlaceObject->ReactivateAndUndo();
lpInPlaceObject->Release();
if (FAILED(m_scLast))
{
Close(); // handle rare failure cases by calling Close
return FALSE;
}
return TRUE;
}
CWnd* COleClientItem::GetInPlaceWindow()
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
// only inplace active items should be asking for the window handle
if (GetItemState() != activeUIState)
return NULL;
// handle case of server that just disappears
if (m_hWndServer != NULL && !::IsWindow(m_hWndServer))
{
Close();
return NULL;
}
ASSERT(m_hWndServer == NULL || ::IsWindow(m_hWndServer));
return CWnd::FromHandle(m_hWndServer);
}
/////////////////////////////////////////////////////////////////////////////
// COleFrameHook OLE interface implementation
BEGIN_INTERFACE_MAP(COleFrameHook, CCmdTarget)
INTERFACE_PART(COleFrameHook, IID_IOleWindow, OleInPlaceFrame)
INTERFACE_PART(COleFrameHook, IID_IOleInPlaceUIWindow, OleInPlaceFrame)
INTERFACE_PART(COleFrameHook, IID_IOleInPlaceFrame, OleInPlaceFrame)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COleFrameHook::XOleInPlaceFrame implementation
STDMETHODIMP_(ULONG) COleFrameHook::XOleInPlaceFrame::AddRef()
{
METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) COleFrameHook::XOleInPlaceFrame::Release()
{
METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
return pThis->ExternalRelease();
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::GetWindow(
HWND* lphwnd)
{
METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
*lphwnd = pThis->m_hWnd;
return *lphwnd != NULL ? S_OK : E_FAIL;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::ContextSensitiveHelp(
BOOL fEnterMode)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
// document frame windows should not be put in help mode, so we get the
// top-level frame window and check it first
CFrameWnd* pFrameWnd = pThis->m_pFrameWnd->GetTopLevelFrame();
ASSERT_VALID(pFrameWnd);
if (fEnterMode)
{
if (!pFrameWnd->m_bHelpMode)
{
// check if help mode probable
if (!pFrameWnd->CanEnterHelpMode())
return E_UNEXPECTED;
// attempt to enter context help
if (!pThis->OnContextHelp(TRUE) ||
!pFrameWnd->PostMessage(WM_COMMAND, ID_CONTEXT_HELP))
{
return E_UNEXPECTED;
}
}
}
else
{
// just exit help mode
pFrameWnd->ExitHelpMode();
}
return S_OK;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::GetBorder(LPRECT lpRectBorder)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
COleClientItem* pItem = pThis->m_pActiveItem;
ASSERT_VALID(pItem);
CFrameWnd* pFrameWnd = pThis->m_pFrameWnd;
ASSERT_VALID(pFrameWnd);
// hide the control bars temporarily
BOOL bHidden = pItem->OnShowControlBars(pFrameWnd, FALSE);
// determine border space assuming that we'll remove our control bars
CRect rectSave = pFrameWnd->m_rectBorder;
#ifndef _MAC
pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderSet, NULL);
#else
if (pFrameWnd->GetActiveView()->GetParentFrame() != pFrameWnd)
{
// MDI only
pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderSet, NULL);
}
#endif
pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderGet, lpRectBorder);
pFrameWnd->NegotiateBorderSpace(CFrameWnd::borderSet, &rectSave);
// restore control bars
if (bHidden)
pItem->OnShowControlBars(pFrameWnd, TRUE);
return S_OK;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::RequestBorderSpace(
LPCRECT lpRectWidths)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
CFrameWnd* pFrameWnd = pThis->m_pFrameWnd;
ASSERT_VALID(pFrameWnd);
if (!pFrameWnd->NegotiateBorderSpace(
CFrameWnd::borderRequest, (LPRECT)lpRectWidths))
{
return INPLACE_E_NOTOOLSPACE;
}
return S_OK;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::SetBorderSpace(
LPCRECT lpRectWidths)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
CFrameWnd* pFrameWnd = pThis->m_pFrameWnd;
if (pFrameWnd->NegotiateBorderSpace(
CFrameWnd::borderSet, (LPRECT)lpRectWidths))
{
pFrameWnd->DelayRecalcLayout(FALSE);
}
pThis->m_pActiveItem->OnShowControlBars(pFrameWnd, lpRectWidths == NULL);
return S_OK;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::SetActiveObject(
LPOLEINPLACEACTIVEOBJECT lpActiveObject, LPCOLESTR lpszObjName)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
// release the old active object
RELEASE(pThis->m_lpActiveObject);
// set the new active object
pThis->m_lpActiveObject = lpActiveObject;
if (lpActiveObject != NULL)
lpActiveObject->AddRef();
// update caption if necessary
pThis->m_strObjName.Empty();
if (lpszObjName != NULL && lpActiveObject != NULL)
{
pThis->m_strObjName = lpszObjName;
pThis->m_pActiveItem->OnUpdateFrameTitle();
}
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::InsertMenus(
HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
// get the associated COleClientItem object
COleClientItem* pItem = pThis->m_pActiveItem;
ASSERT_VALID(pItem);
SCODE sc = E_UNEXPECTED;
TRY
{
pItem->OnInsertMenus(CMenu::FromHandle(hmenuShared), lpMenuWidths);
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::SetMenu(
HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
// get the associated COleClientItem object
COleClientItem* pItem = pThis->m_pActiveItem;
ASSERT_VALID(pItem);
SCODE sc = E_UNEXPECTED;
TRY
{
pItem->OnSetMenu(CMenu::FromHandle(hmenuShared), holemenu,
hwndActiveObject);
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::RemoveMenus(
HMENU hmenuShared)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
// get the associated COleClientItem object
COleClientItem* pItem = pThis->m_pActiveItem;
ASSERT_VALID(pItem);
SCODE sc = E_UNEXPECTED;
TRY
{
pItem->OnRemoveMenus(CMenu::FromHandle(hmenuShared));
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::SetStatusText(
LPCOLESTR lpszStatusText)
{
METHOD_PROLOGUE_EX_(COleFrameHook, OleInPlaceFrame)
USES_CONVERSION;
pThis->m_pFrameWnd->SendMessage(WM_SETMESSAGESTRING, 0,
(LPARAM)OLE2CT(lpszStatusText));
return S_OK;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::EnableModeless(BOOL fEnable)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
ASSERT_VALID(pThis->m_pFrameWnd);
SCODE sc = E_UNEXPECTED;
TRY
{
if (!fEnable)
pThis->m_pFrameWnd->BeginModalState();
else
pThis->m_pFrameWnd->EndModalState();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleFrameHook::XOleInPlaceFrame::TranslateAccelerator(
LPMSG lpmsg, WORD /*wID*/)
{
METHOD_PROLOGUE_EX(COleFrameHook, OleInPlaceFrame)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
// swap accel tables and call PreTranslateMessage
CFrameWnd* pFrameWnd = pThis->m_pFrameWnd;
HACCEL hAccelSave = pFrameWnd->m_hAccelTable;
pFrameWnd->m_hAccelTable = pThis->m_hAccelTable;
ASSERT(lpmsg != NULL);
MSG msg = *lpmsg;
sc = pFrameWnd->PreTranslateMessage(&msg) ? S_OK : S_FALSE;
*lpmsg = msg;
pFrameWnd->m_hAccelTable = hAccelSave;
}
END_TRY
return sc;
}
/////////////////////////////////////////////////////////////////////////////
// COleClientItem::XOleIPSite implementation
STDMETHODIMP_(ULONG) COleClientItem::XOleIPSite::AddRef()
{
METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) COleClientItem::XOleIPSite::Release()
{
METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
return pThis->ExternalRelease();
}
STDMETHODIMP COleClientItem::XOleIPSite::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP COleClientItem::XOleIPSite::GetWindow(HWND* lphwnd)
{
METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
*lphwnd = pThis->m_pView->GetSafeHwnd();
return *lphwnd != NULL ? S_OK : E_FAIL;
}
STDMETHODIMP COleClientItem::XOleIPSite::ContextSensitiveHelp(
BOOL fEnterMode)
{
METHOD_PROLOGUE_EX_(COleClientItem, OleIPSite)
if (pThis->m_pInPlaceFrame == NULL)
return E_UNEXPECTED;
// simply delegate to frame window implementation
return pThis->m_pInPlaceFrame->
m_xOleInPlaceFrame.ContextSensitiveHelp(fEnterMode);
}
STDMETHODIMP COleClientItem::XOleIPSite::CanInPlaceActivate()
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
return pThis->CanActivate() ? S_OK : S_FALSE;
}
STDMETHODIMP COleClientItem::XOleIPSite::OnInPlaceActivate()
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnActivate();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleClientItem::XOleIPSite::OnUIActivate()
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnActivateUI();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleClientItem::XOleIPSite::GetWindowContext(
LPOLEINPLACEFRAME* lplpFrame,
LPOLEINPLACEUIWINDOW* lplpDoc,
LPRECT lpPosRect, LPRECT lpClipRect,
LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
ASSERT_VALID(pThis);
*lplpFrame = NULL; // init these in-case of mem-alloc failure
*lplpDoc = NULL;
CFrameWnd* pMainFrame = NULL;
CFrameWnd* pDocFrame = NULL;
SCODE sc = E_UNEXPECTED;
TRY
{
// get position of the item relative to activation view
CRect rect;
pThis->OnGetItemPosition(rect);
::CopyRect(lpPosRect, &rect);
pThis->OnGetClipRect(rect);
::CopyRect(lpClipRect, &rect);
// get the window context information
if (pThis->OnGetWindowContext(&pMainFrame, &pDocFrame, lpFrameInfo))
{
// hook IOleInPlaceFrame interface to pMainFrame
if (pThis->m_pInPlaceFrame == NULL)
pThis->m_pInPlaceFrame = new COleFrameHook(pMainFrame, pThis);
pThis->m_pInPlaceFrame->InternalAddRef();
*lplpFrame = (LPOLEINPLACEFRAME)pThis->m_pInPlaceFrame->
GetInterface(&IID_IOleInPlaceFrame);
// save accel table for IOleInPlaceFrame::TranslateAccelerators
pThis->m_pInPlaceFrame->m_hAccelTable = lpFrameInfo->haccel;
// hook IOleInPlaceUIWindow to pDocFrame
if (pDocFrame != NULL)
{
if (pThis->m_pInPlaceDoc == NULL)
pThis->m_pInPlaceDoc = new COleFrameHook(pDocFrame, pThis);
pThis->m_pInPlaceDoc->InternalAddRef();
*lplpDoc = (LPOLEINPLACEUIWINDOW)pThis->m_pInPlaceDoc->
GetInterface(&IID_IOleInPlaceUIWindow);
}
sc = S_OK;
}
}
CATCH_ALL(e)
{
// cleanup memory that may be partially allocated
delete *lplpFrame;
ASSERT(*lplpDoc == NULL);
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
return sc;
}
STDMETHODIMP COleClientItem::XOleIPSite::Scroll(SIZE scrollExtent)
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
if (!pThis->OnScrollBy(CSize(scrollExtent)))
sc = S_FALSE;
else
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleClientItem::XOleIPSite::OnUIDeactivate(BOOL fUndoable)
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnDeactivateUI(fUndoable);
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleClientItem::XOleIPSite::OnInPlaceDeactivate()
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnDeactivate();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleClientItem::XOleIPSite::DiscardUndoState()
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnDiscardUndoState();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleClientItem::XOleIPSite::DeactivateAndUndo()
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnDeactivateAndUndo();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP COleClientItem::XOleIPSite::OnPosRectChange(
LPCRECT lpPosRect)
{
METHOD_PROLOGUE_EX(COleClientItem, OleIPSite)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
CRect rect;
rect.CopyRect(lpPosRect);
pThis->OnChangeItemPosition(rect);
sc = S_OK;
}
END_TRY
return sc;
}
/////////////////////////////////////////////////////////////////////////////