mirror of https://github.com/lianthony/NT4.0
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.
2899 lines
69 KiB
2899 lines
69 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"
|
|
#include <shellapi.h>
|
|
|
|
#ifdef AFX_OLE4_SEG
|
|
#pragma code_seg(AFX_OLE4_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc implementation
|
|
|
|
COleServerDoc::COleServerDoc()
|
|
{
|
|
m_lpClientSite = NULL; // will be non-NULL when document is embedding
|
|
m_bCntrVisible = FALSE;
|
|
m_pInPlaceFrame = NULL; // will be non-NULL when in-place active
|
|
m_pOrigParent = NULL;
|
|
m_dwOrigStyle = 0;
|
|
m_dwOrigStyleEx = 0;
|
|
m_bClosing = FALSE;
|
|
m_pEmbeddedItem = NULL; // will be non-NULL if embedded item needed
|
|
}
|
|
|
|
COleServerDoc::~COleServerDoc()
|
|
{
|
|
DeleteContents(); // Note: will not call derived class
|
|
|
|
if (m_pEmbeddedItem != NULL)
|
|
{
|
|
m_pEmbeddedItem->ExternalRelease();
|
|
m_pEmbeddedItem = NULL;
|
|
}
|
|
|
|
// disconnect (remove) all items from the document
|
|
POSITION pos = GetStartPosition();
|
|
COleServerItem* pItem;
|
|
while ((pItem = GetNextServerItem(pos)) != NULL)
|
|
RemoveItem(pItem);
|
|
|
|
// should not be in-place active when doc is destroyed!
|
|
ASSERT(m_pInPlaceFrame == NULL);
|
|
|
|
// Note: this must be done before the client site is released
|
|
RELEASE(m_lpRootStg);
|
|
|
|
// release client-site pointer
|
|
RELEASE(m_lpClientSite);
|
|
}
|
|
|
|
void COleServerDoc::DeleteContents()
|
|
{
|
|
COleLinkingDoc::DeleteContents();
|
|
|
|
// protect all server items with an extra reference count
|
|
POSITION pos = GetStartPosition();
|
|
COleServerItem* pItem;
|
|
while ((pItem = GetNextServerItem(pos)) != NULL)
|
|
pItem->InternalAddRef();
|
|
|
|
// delete any autodelete server items
|
|
pos = GetStartPosition();
|
|
while ((pItem = GetNextServerItem(pos)) != NULL)
|
|
{
|
|
if (pItem->m_bAutoDelete)
|
|
delete pItem;
|
|
}
|
|
|
|
// remove extra reference added above
|
|
pos = GetStartPosition();
|
|
while ((pItem = GetNextServerItem(pos)) != NULL)
|
|
pItem->InternalRelease();
|
|
}
|
|
|
|
COleServerItem* COleServerDoc::GetEmbeddedItem()
|
|
{
|
|
// allocate embedded item if necessary
|
|
if (m_pEmbeddedItem == NULL)
|
|
{
|
|
m_pEmbeddedItem = OnGetEmbeddedItem();
|
|
m_pEmbeddedItem->ExternalAddRef();
|
|
}
|
|
|
|
ASSERT_VALID(m_pEmbeddedItem);
|
|
return m_pEmbeddedItem;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc client notifications
|
|
|
|
void COleServerDoc::NotifyRename(LPCTSTR lpszNewName)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidString(lpszNewName));
|
|
|
|
if (m_pFactory != NULL)
|
|
{
|
|
// update running object table with new moniker
|
|
Revoke();
|
|
Register(m_pFactory, lpszNewName);
|
|
|
|
// notify all items of the new moniker
|
|
POSITION pos = GetStartPosition();
|
|
COleServerItem* pItem;
|
|
while ((pItem = GetNextServerItem(pos)) != NULL)
|
|
{
|
|
// notify client directly
|
|
LPMONIKER lpMoniker = pItem->GetMoniker(OLEGETMONIKER_ONLYIFTHERE);
|
|
pItem->NotifyClient(OLE_RENAMED, (DWORD)lpMoniker);
|
|
RELEASE(lpMoniker);
|
|
}
|
|
}
|
|
}
|
|
|
|
void COleServerDoc::NotifyAllItems(OLE_NOTIFICATION nCode, DWORD dwParam)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
POSITION pos = GetStartPosition();
|
|
COleServerItem* pItem;
|
|
while ((pItem = GetNextServerItem(pos)) != NULL)
|
|
{
|
|
// notify client directly
|
|
pItem->NotifyClient(nCode, dwParam);
|
|
}
|
|
}
|
|
|
|
// UpdateAllItems is much like UpdateAllViews, but for server items
|
|
void COleServerDoc::UpdateAllItems(COleServerItem* pSender,
|
|
LPARAM lHint, CObject* pHint, DVASPECT nDrawAspect)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
POSITION pos = GetStartPosition();
|
|
COleServerItem* pItem;
|
|
while ((pItem = GetNextServerItem(pos)) != NULL)
|
|
{
|
|
// notify client indirectly through OnUpdate
|
|
if (pItem != pSender)
|
|
pItem->OnUpdate(pSender, lHint, pHint, nDrawAspect);
|
|
}
|
|
}
|
|
|
|
void COleServerItem::OnUpdate(COleServerItem* /*pSender*/,
|
|
LPARAM /*lHint*/, CObject* /*pHint*/, DVASPECT nDrawAspect)
|
|
{
|
|
// the default implementation always notifies the container, regardless
|
|
// of the specific hint or sender.
|
|
|
|
NotifyChanged(nDrawAspect);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc attributes
|
|
|
|
BOOL COleServerDoc::GetZoomFactor(LPSIZE lpSizeNum, LPSIZE lpSizeDenom,
|
|
LPCRECT lpPosRect) const
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(lpSizeNum == NULL || AfxIsValidAddress(lpSizeNum, sizeof(SIZE)));
|
|
ASSERT(lpSizeDenom == NULL || AfxIsValidAddress(lpSizeDenom, sizeof(SIZE)));
|
|
ASSERT(lpPosRect == NULL ||
|
|
AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
|
|
|
|
if (!IsInPlaceActive())
|
|
{
|
|
if (lpSizeNum != NULL)
|
|
{
|
|
ASSERT(lpSizeDenom != NULL);
|
|
lpSizeNum->cx = 1;
|
|
lpSizeNum->cy = 1;
|
|
*lpSizeDenom = *lpSizeNum;
|
|
}
|
|
return FALSE;
|
|
}
|
|
ASSERT_VALID(m_pInPlaceFrame);
|
|
|
|
// the zoom factor is (Size(position-rect) / m_sizeExtent)
|
|
CSize sizeNum;
|
|
if (lpPosRect == NULL)
|
|
{
|
|
// use current position rect
|
|
sizeNum = m_pInPlaceFrame->m_rectPos.Size();
|
|
}
|
|
else
|
|
{
|
|
// use new position rect
|
|
sizeNum.cx = lpPosRect->right - lpPosRect->left;
|
|
sizeNum.cy = lpPosRect->bottom - lpPosRect->top;
|
|
}
|
|
|
|
// m_sizeExtent is in HIMETRIC units -- need to convert to pixels.
|
|
CSize sizeDenom(0, 0);
|
|
COleServerItem* pItem = ((COleServerDoc*)this)->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
|
|
// get zoom denominator, which is based on the current extent
|
|
((COleServerItem*)pItem)->OnGetExtent(DVASPECT_CONTENT, sizeDenom);
|
|
if (sizeDenom.cx == 0 || sizeDenom.cy == 0)
|
|
{
|
|
// no extent from container available, so use natural extent instead
|
|
pItem->OnGetExtent(DVASPECT_CONTENT, sizeDenom);
|
|
}
|
|
// convert extent to pixels first
|
|
((CDC*)NULL)->HIMETRICtoDP(&sizeDenom);
|
|
|
|
// might be bad to have zoom denominator of zero!
|
|
if (sizeDenom.cy == 0 || sizeDenom.cx == 0)
|
|
{
|
|
TRACE0("Warning: zero 'zoom denominator', using 100%% zoom instead.\n");
|
|
sizeDenom = sizeNum;
|
|
}
|
|
|
|
// store the results
|
|
if (lpSizeNum != NULL)
|
|
{
|
|
ASSERT(lpSizeDenom != NULL);
|
|
*lpSizeNum = sizeNum;
|
|
*lpSizeDenom = sizeDenom;
|
|
}
|
|
|
|
// if 100% scaling, return FALSE
|
|
return sizeNum != sizeDenom;
|
|
}
|
|
|
|
void COleServerDoc::GetItemPosition(LPRECT lpPosRect) const
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT)));
|
|
ASSERT(IsInPlaceActive());
|
|
ASSERT_VALID(m_pInPlaceFrame);
|
|
|
|
// copy the current rectangle
|
|
*lpPosRect = m_pInPlaceFrame->m_rectPos;
|
|
}
|
|
|
|
void COleServerDoc::GetItemClipRect(LPRECT lpClipRect) const
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(lpClipRect, sizeof(RECT)));
|
|
ASSERT(IsInPlaceActive());
|
|
ASSERT_VALID(m_pInPlaceFrame);
|
|
|
|
// copy the current rectangle
|
|
*lpClipRect = m_pInPlaceFrame->m_rectClip;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc overrideables
|
|
|
|
COleServerItem* COleServerDoc::OnGetLinkedItem(LPCTSTR lpszItemName)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidString(lpszItemName));
|
|
|
|
// default implementation walks list of server items looking for
|
|
// a case sensitive match
|
|
|
|
POSITION pos = GetStartPosition();
|
|
COleServerItem* pItem;
|
|
while ((pItem = GetNextServerItem(pos)) != NULL)
|
|
{
|
|
// return item if name matches (case sensitive)
|
|
if (lstrcmp(pItem->GetItemName(), lpszItemName) == 0)
|
|
return pItem;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
if (afxTraceFlags & traceOle)
|
|
{
|
|
TRACE0("Warning: default COleServerDoc::OnGetLinkedItem implementation\n");
|
|
TRACE1("\tfailed to find item '%s'.\n", lpszItemName);
|
|
}
|
|
#endif
|
|
return NULL; // not found (no link found)
|
|
}
|
|
|
|
void COleServerDoc::OnClose(OLECLOSE dwCloseOption)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// do nothing if already in the process of closing the document
|
|
if (m_bClosing)
|
|
return;
|
|
|
|
// OLECLOSE_PROMPTSAVE is handled like OLECLOSE_SAVEIFDIRTY if invisible
|
|
CFrameWnd* pFrameWnd = GetFirstFrame();
|
|
if (pFrameWnd != NULL && pFrameWnd->IsWindowVisible())
|
|
dwCloseOption = OLECLOSE_SAVEIFDIRTY;
|
|
|
|
// handle modified document and special dwCloseOption flags
|
|
TRY
|
|
{
|
|
if (IsModified())
|
|
{
|
|
switch (dwCloseOption)
|
|
{
|
|
case OLECLOSE_PROMPTSAVE:
|
|
if (!SaveModifiedPrompt())
|
|
AfxThrowOleException(OLE_E_PROMPTSAVECANCELLED);
|
|
break;
|
|
|
|
case OLECLOSE_SAVEIFDIRTY:
|
|
SaveEmbedding();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
END_TRY
|
|
|
|
// deactivate in-place session
|
|
if (m_pInPlaceFrame != NULL)
|
|
{
|
|
OnDeactivate();
|
|
ASSERT(m_pInPlaceFrame == NULL);
|
|
}
|
|
|
|
// close the document
|
|
BOOL bAutoDelete = m_bAutoDelete;
|
|
m_bAutoDelete = FALSE;
|
|
OnCloseDocument();
|
|
m_bAutoDelete = bAutoDelete;
|
|
}
|
|
|
|
BOOL COleServerDoc::SaveModifiedPrompt()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
if (m_lpClientSite == NULL)
|
|
return SaveModified();
|
|
|
|
UpdateModifiedFlag(); // check for modified client items
|
|
|
|
if (!IsModified())
|
|
return TRUE; // ok to continue
|
|
|
|
CString prompt;
|
|
AfxFormatString1(prompt, AFX_IDP_ASK_TO_UPDATE, m_strTitle);
|
|
switch (AfxMessageBox(prompt, MB_YESNOCANCEL, AFX_IDP_ASK_TO_UPDATE))
|
|
{
|
|
case IDCANCEL:
|
|
return FALSE; // don't continue
|
|
|
|
case IDYES:
|
|
if (!OnUpdateDocument())
|
|
{
|
|
TRACE0("Warning: OnUpdateDocument failed to update.\n");
|
|
// keep going, close will flush it
|
|
}
|
|
break;
|
|
}
|
|
return TRUE; // keep going
|
|
}
|
|
|
|
BOOL COleServerDoc::CanCloseFrame(CFrameWnd* pFrame)
|
|
{
|
|
m_bClosing = TRUE;
|
|
if (!COleLinkingDoc::CanCloseFrame(pFrame))
|
|
{
|
|
m_bClosing = FALSE;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COleServerDoc::GetFileTypeString(CString& rString)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
CDocTemplate* pTemplate = GetDocTemplate();
|
|
if (pTemplate == NULL)
|
|
return FALSE;
|
|
|
|
pTemplate->GetDocString(rString, CDocTemplate::fileNewName);
|
|
return !rString.IsEmpty();
|
|
}
|
|
|
|
void COleServerDoc::OnSetHostNames(LPCTSTR lpszHost, LPCTSTR lpszHostObj)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(lpszHost == NULL || AfxIsValidString(lpszHost));
|
|
ASSERT(lpszHostObj == NULL || AfxIsValidString(lpszHostObj));
|
|
UNUSED(lpszHost); // unused in release builds
|
|
|
|
// only change the title for embedded documents
|
|
if (m_lpClientSite != NULL)
|
|
{
|
|
// save name of document for File.Exit update
|
|
if (lpszHostObj == NULL)
|
|
m_strHostObj.LoadString(AFX_IDS_UNTITLED);
|
|
else
|
|
m_strHostObj = lpszHostObj;
|
|
|
|
// attempt to get the document name from the document template
|
|
CString strFileType;
|
|
if (!GetFileTypeString(strFileType))
|
|
return;
|
|
|
|
// format the string into <server-name> in <docname>
|
|
CString strTitle;
|
|
AfxFormatString2(strTitle, AFX_IDS_APP_TITLE_EMBEDDING,
|
|
strFileType, m_strHostObj);
|
|
|
|
// change title of document to that for an embedded item
|
|
// (this call will update all of the frames)
|
|
SetTitle(strTitle);
|
|
}
|
|
}
|
|
|
|
void COleServerDoc::SaveEmbedding()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// tell the client site to save the object
|
|
if (m_lpClientSite != NULL && !::InSendMessage())
|
|
{
|
|
SCODE sc = m_lpClientSite->SaveObject();
|
|
if (sc != S_OK)
|
|
AfxThrowOleException(sc);
|
|
}
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
BOOL COleServerDoc::OnUpdateDocument()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// don't save if already up-to-date
|
|
if (!IsModified())
|
|
return TRUE;
|
|
|
|
// save a server document -> update
|
|
TRY
|
|
{
|
|
SaveEmbedding();
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
AfxMessageBox(AFX_IDP_FAILED_TO_UPDATE);
|
|
DELETE_EXCEPTION(e);
|
|
return FALSE;
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LPMONIKER COleServerDoc::GetMoniker(OLEGETMONIKER nAssign)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
if (m_lpClientSite != NULL)
|
|
{
|
|
// get moniker from client site instead of from document
|
|
LPMONIKER lpMoniker = NULL;
|
|
m_lpClientSite->GetMoniker(nAssign, OLEWHICHMK_OBJFULL, &lpMoniker);
|
|
return lpMoniker;
|
|
}
|
|
|
|
return COleLinkingDoc::GetMoniker(nAssign);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc document handling
|
|
|
|
BOOL COleServerDoc::SaveModified()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
if (m_lpClientSite != NULL)
|
|
{
|
|
if (m_pInPlaceFrame == NULL)
|
|
{
|
|
UpdateModifiedFlag(); // check for modified items
|
|
OnUpdateDocument();
|
|
}
|
|
return TRUE;
|
|
}
|
|
return COleLinkingDoc::SaveModified();
|
|
}
|
|
|
|
HMENU COleServerDoc::GetDefaultMenu()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
CDocTemplate* pTemplate = GetDocTemplate();
|
|
if (pTemplate == NULL)
|
|
return NULL; // no doc template -- use default
|
|
|
|
ASSERT_VALID(pTemplate);
|
|
if (m_pInPlaceFrame != NULL)
|
|
return pTemplate->m_hMenuInPlaceServer; // return special in-place menu
|
|
else if (m_lpClientSite != NULL)
|
|
return pTemplate->m_hMenuEmbedding; // return special embedding menu
|
|
|
|
return NULL; // no special mode, use default menu
|
|
}
|
|
|
|
HACCEL COleServerDoc::GetDefaultAccelerator()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
CDocTemplate* pTemplate = GetDocTemplate();
|
|
if (pTemplate == NULL)
|
|
return NULL; // no doc template -- use default
|
|
|
|
ASSERT_VALID(pTemplate);
|
|
if (m_pInPlaceFrame != NULL)
|
|
return pTemplate->m_hAccelInPlaceServer; // return special in-place accel
|
|
else if (m_lpClientSite != NULL)
|
|
return pTemplate->m_hAccelEmbedding;// return special embedding accel
|
|
|
|
return NULL; // no special mode, use default menu
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc default command handling
|
|
|
|
BEGIN_MESSAGE_MAP(COleServerDoc, COleLinkingDoc)
|
|
//{{AFX_MSG_MAP(COleServerDoc)
|
|
ON_COMMAND(ID_FILE_UPDATE, OnFileUpdate)
|
|
ON_COMMAND(ID_FILE_SAVE_COPY_AS, OnFileSaveCopyAs)
|
|
ON_UPDATE_COMMAND_UI(ID_APP_EXIT, OnUpdateFileExit)
|
|
ON_UPDATE_COMMAND_UI(ID_FILE_UPDATE, OnUpdateFileUpdate)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
void COleServerDoc::OnFileUpdate()
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_lpClientSite != NULL);
|
|
|
|
UpdateModifiedFlag();
|
|
OnUpdateDocument();
|
|
}
|
|
|
|
void COleServerDoc::OnFileSaveCopyAs()
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_bRemember);
|
|
ASSERT(m_lpClientSite != NULL);
|
|
|
|
LPSTORAGE lpOrigStg = m_lpRootStg;
|
|
m_lpRootStg = NULL; // ignore embedded storage for now
|
|
|
|
TRY
|
|
{
|
|
// call DoSave to perform Save Copy As...
|
|
m_bRemember = FALSE;
|
|
DoSave(NULL, FALSE);
|
|
}
|
|
END_TRY
|
|
|
|
m_lpRootStg = lpOrigStg;
|
|
m_bRemember = TRUE;
|
|
}
|
|
|
|
void COleServerDoc::UpdateUsingHostObj(UINT nIDS, CCmdUI* pCmdUI)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(pCmdUI != NULL);
|
|
|
|
if (m_lpClientSite == NULL)
|
|
return;
|
|
|
|
// update menu item using m_strHostObj
|
|
CString str;
|
|
AfxFormatString1(str, nIDS, m_strHostObj);
|
|
if (!str.IsEmpty())
|
|
pCmdUI->SetText(str);
|
|
}
|
|
|
|
void COleServerDoc::OnUpdateFileExit(CCmdUI* pCmdUI)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(pCmdUI != NULL);
|
|
|
|
UpdateUsingHostObj(AFX_IDS_EXIT_MENU, pCmdUI);
|
|
}
|
|
|
|
void COleServerDoc::OnUpdateFileUpdate(CCmdUI* pCmdUI)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(pCmdUI != NULL);
|
|
|
|
UpdateUsingHostObj(AFX_IDS_UPDATE_MENU, pCmdUI);
|
|
}
|
|
|
|
BOOL COleServerDoc::OnSaveDocument(LPCTSTR lpszPathName)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
|
|
|
|
BOOL bRemember = m_bRemember;
|
|
if (!COleLinkingDoc::OnSaveDocument(lpszPathName))
|
|
return FALSE;
|
|
|
|
if (lpszPathName != NULL && bRemember)
|
|
{
|
|
if (AfxComparePath(GetPathName(), lpszPathName))
|
|
NotifySaved();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void COleServerDoc::OnCloseDocument()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// don't allow in-place active documents to be closed without first
|
|
// deactivating them!
|
|
if (m_pInPlaceFrame != NULL)
|
|
{
|
|
if (GetFirstViewPosition() != NULL)
|
|
return;
|
|
|
|
// no views but currently in-place active indicates that
|
|
// a WM_ENDSESSION is being processed.
|
|
m_pInPlaceFrame = NULL;
|
|
}
|
|
|
|
InternalAddRef(); // keep document stable during shutdown
|
|
|
|
// update lock count before sending notifications
|
|
UpdateVisibleLock(FALSE, FALSE);
|
|
|
|
// send some notifications to the container
|
|
if (m_lpClientSite != NULL && m_bCntrVisible)
|
|
{
|
|
// allow the container to unshade the object appropriately
|
|
m_lpClientSite->OnShowWindow(FALSE);
|
|
m_bCntrVisible = FALSE;
|
|
}
|
|
|
|
// send close notification
|
|
NotifyClosed();
|
|
|
|
// finish closing the document (before m_lpClientSite->Release)
|
|
BOOL bAutoDelete = m_bAutoDelete;
|
|
m_bAutoDelete = FALSE;
|
|
COleLinkingDoc::OnCloseDocument();
|
|
ASSERT_VALID(this);
|
|
|
|
// release client-site pointer
|
|
RELEASE(m_lpClientSite);
|
|
|
|
// disconnect the object
|
|
LPUNKNOWN lpUnknown = (LPUNKNOWN)GetInterface(&IID_IUnknown);
|
|
ASSERT(lpUnknown != NULL);
|
|
CoDisconnectObject(lpUnknown, 0);
|
|
|
|
// destroy the document if allowed
|
|
InterlockedDecrement(&m_dwRef); // remove InternalAddRef above
|
|
if (bAutoDelete)
|
|
delete this;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc show/hide
|
|
|
|
void COleServerDoc::OnShowDocument(BOOL bShow)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
CWinApp* pApp = AfxGetApp();
|
|
if (bShow)
|
|
{
|
|
// deactivate in-place session if active
|
|
if (m_pInPlaceFrame != NULL)
|
|
{
|
|
OnDeactivate();
|
|
ASSERT(m_pInPlaceFrame == NULL);
|
|
}
|
|
|
|
// find the first view of this document
|
|
CFrameWnd* pFrameWnd;
|
|
if ((pFrameWnd = GetFirstFrame()) != NULL)
|
|
{
|
|
// allow container to show & scroll to the object
|
|
if (!pFrameWnd->IsWindowVisible() && m_lpClientSite != NULL)
|
|
m_lpClientSite->ShowObject();
|
|
|
|
// activate frame holding view
|
|
ASSERT_VALID(pFrameWnd);
|
|
pFrameWnd->ActivateFrame();
|
|
|
|
// activate application if necessary
|
|
CFrameWnd* pAppFrame = pFrameWnd->GetParentFrame();
|
|
if (pAppFrame != NULL)
|
|
{
|
|
pFrameWnd = pAppFrame;
|
|
ASSERT_VALID(pFrameWnd);
|
|
ASSERT_KINDOF(CFrameWnd, pFrameWnd);
|
|
pFrameWnd->ActivateFrame();
|
|
}
|
|
pFrameWnd->GetLastActivePopup()->SetForegroundWindow();
|
|
|
|
// update the menu and title as appropriate for this document
|
|
pFrameWnd->OnUpdateFrameMenu(NULL);
|
|
pFrameWnd->OnUpdateFrameTitle(TRUE);
|
|
}
|
|
else if (pApp->m_pMainWnd != NULL)
|
|
{
|
|
// otherwise, just show the main window (for simple servers)
|
|
CWnd* pWnd = AfxGetMainWnd();
|
|
|
|
// allow container to show & scroll to the object
|
|
if (!pWnd->IsWindowVisible() && m_lpClientSite != NULL)
|
|
m_lpClientSite->ShowObject();
|
|
|
|
pWnd->ShowWindow(SW_SHOW);
|
|
pWnd->SetActiveWindow();
|
|
pWnd->SetForegroundWindow();
|
|
}
|
|
|
|
// for file based documents, showing the document puts user in control.
|
|
if (!m_bEmbedded)
|
|
AfxOleSetUserCtrl(TRUE);
|
|
}
|
|
else
|
|
{
|
|
if (m_pInPlaceFrame != NULL)
|
|
{
|
|
// hide has semantics of DeactivateUI if the item is active
|
|
if (m_pInPlaceFrame->m_bUIActive)
|
|
OnDeactivateUI(FALSE);
|
|
|
|
// and then hide the frame itself
|
|
if (m_pInPlaceFrame != NULL)
|
|
m_pInPlaceFrame->ActivateFrame(SW_HIDE);
|
|
return;
|
|
}
|
|
|
|
// find the first view of this document
|
|
POSITION pos = GetFirstViewPosition();
|
|
if (pos != NULL)
|
|
{
|
|
CFrameWnd* pDocFrame = GetFirstFrame();
|
|
CFrameWnd* pActiveFrame = NULL;
|
|
CFrameWnd* pMainFrame = NULL;
|
|
CView* pView = GetNextView(pos);
|
|
ASSERT_VALID(pView);
|
|
|
|
// destroy or hide all the frames for this document
|
|
// (the main for the document is hidden, where the alternate
|
|
// frames are simply destroyed)
|
|
do
|
|
{
|
|
// hide frame holding view
|
|
CFrameWnd* pFrame = pView->GetParentFrame();
|
|
ASSERT_VALID(pFrame);
|
|
|
|
// determine next valid view before destroying the frame
|
|
while ((pView = GetNextView(pos)) != NULL)
|
|
{
|
|
if (pView->GetParentFrame() != pFrame)
|
|
break;
|
|
}
|
|
|
|
pMainFrame = pFrame->GetParentFrame();
|
|
if (pMainFrame != NULL && pMainFrame->GetActiveFrame() == pFrame)
|
|
{
|
|
// don't destroy the active frame until later
|
|
pActiveFrame = pFrame;
|
|
}
|
|
else
|
|
{
|
|
// not the active frame -- destroy/hide it now
|
|
PreCloseFrame(pFrame);
|
|
if (pDocFrame == pFrame)
|
|
pFrame->ActivateFrame(SW_HIDE);
|
|
else
|
|
pFrame->DestroyWindow();
|
|
}
|
|
|
|
} while (pView != NULL);
|
|
|
|
// hide the active frame last
|
|
if (pActiveFrame != NULL)
|
|
{
|
|
PreCloseFrame(pActiveFrame);
|
|
if (pDocFrame == pActiveFrame)
|
|
pActiveFrame->ActivateFrame(SW_HIDE);
|
|
else
|
|
pActiveFrame->DestroyWindow();
|
|
|
|
// should leave at least one frame
|
|
ASSERT_VALID(this);
|
|
ASSERT_VALID(GetFirstFrame());
|
|
}
|
|
}
|
|
|
|
CFrameWnd* pMainFrame = (CFrameWnd*)pApp->m_pMainWnd;
|
|
if (!AfxOleGetUserCtrl() && pMainFrame != NULL &&
|
|
pMainFrame->IsWindowEnabled() && pMainFrame->IsFrameWnd() &&
|
|
pMainFrame->GetActiveFrame() == pMainFrame)
|
|
{
|
|
// hide the entire application -- no visible documents left
|
|
pApp->HideApplication();
|
|
}
|
|
}
|
|
|
|
// send OnShowWindow notifications to the container
|
|
if (m_lpClientSite != NULL && (bShow || m_bCntrVisible != bShow))
|
|
{
|
|
// allow the container to shade the object appropriately
|
|
m_lpClientSite->OnShowWindow(bShow);
|
|
m_bCntrVisible = bShow;
|
|
}
|
|
|
|
// force update visible lock
|
|
if (bShow)
|
|
UpdateVisibleLock(TRUE, FALSE);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc storage implementation
|
|
|
|
void COleServerDoc::OnNewEmbedding(LPSTORAGE lpStorage)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(lpStorage != NULL);
|
|
|
|
// save state
|
|
BOOL bUserCtrl = AfxOleGetUserCtrl();
|
|
|
|
TRY
|
|
{
|
|
// remember new storage
|
|
DeleteContents();
|
|
lpStorage->AddRef();
|
|
RELEASE(m_lpRootStg);
|
|
m_lpRootStg = lpStorage;
|
|
m_strPathName.Empty();
|
|
m_bEmbedded = TRUE;
|
|
|
|
// do document initialization by calling OnNewDocument
|
|
if (!OnNewDocument())
|
|
AfxThrowMemoryException();
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
// restore state
|
|
AfxOleSetUserCtrl(bUserCtrl);
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
// restore state
|
|
AfxOleSetUserCtrl(bUserCtrl);
|
|
|
|
SetModifiedFlag(); // new storage-based documents are dirty!
|
|
SendInitialUpdate();
|
|
}
|
|
|
|
void COleServerDoc::OnOpenEmbedding(LPSTORAGE lpStorage)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(lpStorage != NULL);
|
|
|
|
// save state
|
|
BOOL bUserCtrl = AfxOleGetUserCtrl();
|
|
|
|
TRY
|
|
{
|
|
// abort changes to current document
|
|
DeleteContents();
|
|
lpStorage->AddRef();
|
|
RELEASE(m_lpRootStg);
|
|
m_lpRootStg = lpStorage;
|
|
|
|
// open document from the sub-storage
|
|
if (!OnOpenDocument(NULL))
|
|
AfxThrowMemoryException();
|
|
|
|
// now document is storage based
|
|
m_strPathName.Empty();
|
|
m_bEmbedded = TRUE;
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
// restore state
|
|
AfxOleSetUserCtrl(bUserCtrl);
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
// restore state
|
|
AfxOleSetUserCtrl(bUserCtrl);
|
|
|
|
SetModifiedFlag(FALSE); // start off with unmodified
|
|
SendInitialUpdate();
|
|
}
|
|
|
|
void COleServerDoc::OnSaveEmbedding(LPSTORAGE lpStorage)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(lpStorage != NULL);
|
|
|
|
// save state
|
|
BOOL bUserCtrl = AfxOleGetUserCtrl();
|
|
|
|
// check for save as
|
|
LPSTORAGE lpOrigStg = m_lpRootStg;
|
|
if (!m_bSameAsLoad)
|
|
{
|
|
// File Save[Copy] As (saving to different file)
|
|
ASSERT(lpStorage != NULL);
|
|
m_lpRootStg = lpStorage;
|
|
}
|
|
|
|
TRY
|
|
{
|
|
// save document to the sub-storage
|
|
if (!OnSaveDocument(NULL))
|
|
AfxThrowMemoryException();
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
// restore state
|
|
AfxOleSetUserCtrl(bUserCtrl);
|
|
// re-attach original storage
|
|
m_lpRootStg = lpOrigStg;
|
|
THROW_LAST();
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
// restore state
|
|
AfxOleSetUserCtrl(bUserCtrl);
|
|
|
|
// re-attach original storage
|
|
m_lpRootStg = lpOrigStg;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc in-place activation implementation
|
|
|
|
BOOL COleServerDoc::ActivateInPlace()
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
ASSERT_VALID(this);
|
|
LPCOLESTR lpszTitle = NULL;
|
|
|
|
if (m_lpClientSite == NULL)
|
|
return FALSE; // no client-side (may be a link)
|
|
|
|
// activate already in-place window if currently in-place active
|
|
if (m_pInPlaceFrame != NULL)
|
|
{
|
|
if (m_pInPlaceFrame->m_bUIActive)
|
|
{
|
|
m_lpClientSite->ShowObject(); // object should get focus
|
|
return TRUE;
|
|
}
|
|
// deactivate in-place session entirely before continuing
|
|
OnDeactivate();
|
|
}
|
|
|
|
// fail if already fully open
|
|
if (GetFirstFrame()->IsWindowVisible())
|
|
return FALSE;
|
|
|
|
// build object title/name (the container may use this in its caption)
|
|
CString strFileType, strTitle;
|
|
if (!GetFileTypeString(strFileType))
|
|
return FALSE;
|
|
AfxFormatString2(strTitle, AFX_IDS_OBJ_TITLE_INPLACE,
|
|
AfxGetAppName(), strFileType);
|
|
|
|
// attempt to get in-place client-site interface
|
|
LPOLEINPLACESITE lpInPlaceSite =
|
|
QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
|
|
if (lpInPlaceSite == NULL)
|
|
{
|
|
// unable to get in-place client site interface
|
|
return FALSE;
|
|
}
|
|
|
|
// see if the container wants to go in-place right now
|
|
if (lpInPlaceSite->CanInPlaceActivate() != S_OK)
|
|
goto ReleaseAndFail;
|
|
|
|
// start activation sequence...
|
|
|
|
if (lpInPlaceSite->OnInPlaceActivate() != S_OK)
|
|
goto ReleaseAndFail;
|
|
|
|
// we'll need the parent window to create the COleIPFrameWnd
|
|
HWND hWnd;
|
|
VERIFY(lpInPlaceSite->GetWindow(&hWnd) == S_OK);
|
|
CWnd* pParentWnd;
|
|
pParentWnd = CWnd::FromHandle(hWnd);
|
|
|
|
// create the inplace frame window
|
|
COleIPFrameWnd* pFrameWnd;
|
|
pFrameWnd = CreateInPlaceFrame(pParentWnd);
|
|
if (pFrameWnd == NULL)
|
|
{
|
|
ASSERT(lpInPlaceSite != NULL);
|
|
lpInPlaceSite->OnInPlaceDeactivate();
|
|
goto ReleaseAndFail;
|
|
}
|
|
ASSERT(pFrameWnd->GetParent() == pParentWnd);
|
|
m_pInPlaceFrame = pFrameWnd;
|
|
|
|
// send activate notification
|
|
if (lpInPlaceSite->OnUIActivate() != S_OK)
|
|
goto DestroyFrameAndFail;
|
|
|
|
// need to get frame & doc window interfaces as well as other info
|
|
RECT rcPosRect, rcClipRect;
|
|
if (lpInPlaceSite->GetWindowContext(
|
|
&pFrameWnd->m_lpFrame, &pFrameWnd->m_lpDocFrame,
|
|
&rcPosRect, &rcClipRect, &pFrameWnd->m_frameInfo) != S_OK)
|
|
{
|
|
goto DeactivateUIAndFail;
|
|
}
|
|
ASSERT(pFrameWnd->m_lpFrame != NULL);
|
|
|
|
// setup the shared menu
|
|
if (!pFrameWnd->BuildSharedMenu())
|
|
goto DeactivateUIAndFail;
|
|
|
|
// allow server to install frame controls in container
|
|
VERIFY(pFrameWnd->m_lpFrame->GetWindow(&hWnd) == S_OK);
|
|
pFrameWnd->m_pMainFrame = new COleCntrFrameWnd(pFrameWnd);
|
|
pFrameWnd->m_pMainFrame->Attach(hWnd);
|
|
if (pFrameWnd->m_lpDocFrame != NULL)
|
|
{
|
|
VERIFY(pFrameWnd->m_lpDocFrame->GetWindow(&hWnd) == S_OK);
|
|
pFrameWnd->m_pDocFrame = new COleCntrFrameWnd(pFrameWnd);
|
|
pFrameWnd->m_pDocFrame->Attach(hWnd);
|
|
}
|
|
// update zoom factor information before creating control bars
|
|
pFrameWnd->m_rectPos.CopyRect(&rcPosRect);
|
|
pFrameWnd->m_rectClip.CopyRect(&rcClipRect);
|
|
if (!pFrameWnd->OnCreateControlBars(pFrameWnd->m_pMainFrame,
|
|
pFrameWnd->m_pDocFrame))
|
|
{
|
|
goto DeactivateUIAndFail;
|
|
}
|
|
|
|
// resize the window to match the object
|
|
OnSetItemRects(&rcPosRect, &rcClipRect);
|
|
|
|
// set the active object
|
|
ASSERT(pFrameWnd->m_lpFrame != NULL);
|
|
LPOLEINPLACEACTIVEOBJECT lpActiveObject;
|
|
lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
|
|
GetInterface(&IID_IOleInPlaceActiveObject);
|
|
lpszTitle = T2COLE(strTitle);
|
|
pFrameWnd->m_lpFrame->SetActiveObject(lpActiveObject, lpszTitle);
|
|
if (pFrameWnd->m_lpDocFrame != NULL)
|
|
pFrameWnd->m_lpDocFrame->SetActiveObject(lpActiveObject, lpszTitle);
|
|
|
|
// add frame & document level frame controls
|
|
ASSERT(m_pInPlaceFrame->m_lpFrame != NULL);
|
|
OnShowControlBars(m_pInPlaceFrame->m_pMainFrame, TRUE);
|
|
if (m_pInPlaceFrame->m_lpDocFrame != NULL)
|
|
OnShowControlBars(m_pInPlaceFrame->m_pDocFrame, TRUE);
|
|
|
|
// show any hidden modeless dialogs as well...
|
|
m_pInPlaceFrame->ShowOwnedWindows(TRUE);
|
|
|
|
// attempt toolbar negotiation
|
|
OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
|
|
if (pFrameWnd->m_lpDocFrame != NULL)
|
|
OnResizeBorder(NULL, pFrameWnd->m_lpDocFrame, FALSE);
|
|
|
|
// install the menu (also installs a hook which forwards messages from
|
|
// the menu to the inplace frame window)
|
|
pFrameWnd->m_lpFrame->SetMenu(pFrameWnd->m_hSharedMenu,
|
|
pFrameWnd->m_hOleMenu, pFrameWnd->m_hWnd);
|
|
|
|
// make sure object is scrolled into view
|
|
m_lpClientSite->ShowObject(); // object should get focus
|
|
|
|
// finally -- show the inplace frame window and set focus
|
|
pFrameWnd->ShowWindow(SW_SHOW);
|
|
pFrameWnd->SetFocus();
|
|
pFrameWnd->UpdateWindow();
|
|
UpdateVisibleLock(TRUE, FALSE);
|
|
|
|
// allow the main window to be set
|
|
OnFrameWindowActivate(TRUE);
|
|
pFrameWnd->m_bUIActive = TRUE;
|
|
|
|
// cleanup and return
|
|
lpInPlaceSite->Release();
|
|
return TRUE;
|
|
|
|
DeactivateUIAndFail:
|
|
ASSERT(lpInPlaceSite != NULL);
|
|
lpInPlaceSite->OnUIDeactivate(FALSE);
|
|
|
|
DestroyFrameAndFail:
|
|
if (m_pInPlaceFrame != NULL)
|
|
{
|
|
ASSERT(pFrameWnd != NULL);
|
|
DestroyInPlaceFrame(pFrameWnd);
|
|
m_pInPlaceFrame = NULL;
|
|
|
|
// also need to send OnInPlaceDeactivate notification
|
|
ASSERT(lpInPlaceSite != NULL);
|
|
lpInPlaceSite->OnInPlaceDeactivate();
|
|
}
|
|
|
|
ReleaseAndFail:
|
|
ASSERT(lpInPlaceSite != NULL);
|
|
lpInPlaceSite->Release();
|
|
return FALSE;
|
|
}
|
|
|
|
COleIPFrameWnd* COleServerDoc::CreateInPlaceFrame(CWnd* pParentWnd)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT_VALID(pParentWnd);
|
|
|
|
// get runtime class from the doc template
|
|
CDocTemplate* pTemplate = GetDocTemplate();
|
|
ASSERT_VALID(pTemplate);
|
|
|
|
// use existing view if possible
|
|
CWnd* pViewParent = NULL;
|
|
CView* pView = NULL;
|
|
CFrameWnd* pFrame = GetFirstFrame();
|
|
if (pFrame != NULL)
|
|
{
|
|
pView = (CView*)pFrame->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
|
|
if (pView != NULL)
|
|
{
|
|
ASSERT_KINDOF(CView, pView);
|
|
pViewParent = pView->GetParent();
|
|
m_dwOrigStyle = pView->GetStyle();
|
|
m_dwOrigStyleEx = pView->GetExStyle();
|
|
}
|
|
}
|
|
|
|
// create the frame from the template
|
|
COleIPFrameWnd* pFrameWnd = (COleIPFrameWnd*)
|
|
pTemplate->CreateOleFrame(pParentWnd, this, pView == NULL);
|
|
if (pFrameWnd == NULL)
|
|
return NULL;
|
|
|
|
// connect the view to the frame window, if necessary
|
|
if (pView != NULL)
|
|
{
|
|
ConnectView(pFrameWnd, pView);
|
|
pView->ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_DRAWFRAME);
|
|
}
|
|
|
|
// remember original parent window for deactivate
|
|
m_pOrigParent = pViewParent;
|
|
|
|
// send OnInitialUpdate if new view was created
|
|
if (pView == NULL)
|
|
pTemplate->InitialUpdateFrame(pFrameWnd, this, FALSE);
|
|
|
|
// verify the type
|
|
ASSERT_VALID(pFrameWnd);
|
|
ASSERT_KINDOF(COleIPFrameWnd, pFrameWnd);
|
|
return pFrameWnd;
|
|
}
|
|
|
|
void COleServerDoc::DestroyInPlaceFrame(COleIPFrameWnd* pFrameWnd)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT_VALID(pFrameWnd);
|
|
|
|
// connect view to original, if existing view was used
|
|
if (m_pOrigParent != NULL)
|
|
{
|
|
CView* pView = (CView*)pFrameWnd->GetDescendantWindow(
|
|
AFX_IDW_PANE_FIRST, TRUE);
|
|
ASSERT_VALID(pView);
|
|
|
|
// leaving the focus on an MDI child or one of its child windows
|
|
// causes Windows to get confused when the child window is
|
|
// destroyed, not to mention the fact that the focus will be
|
|
// out of sync with activation.
|
|
if (::GetFocus() == pView->m_hWnd)
|
|
{
|
|
// move focus to somewhere safe
|
|
HWND hWnd = ::GetParent(pFrameWnd->m_hWnd);
|
|
if (hWnd != NULL)
|
|
::SetFocus(hWnd);
|
|
|
|
// check again
|
|
if (::GetFocus() == pView->m_hWnd)
|
|
SetFocus(NULL); // last ditch effort
|
|
}
|
|
|
|
ConnectView(m_pOrigParent, pView);
|
|
m_pOrigParent = NULL;
|
|
|
|
// remove any scrollbars added because of in-place activation
|
|
if ((m_dwOrigStyle & (WS_HSCROLL|WS_VSCROLL)) == 0 &&
|
|
(pView->GetStyle() & (WS_HSCROLL|WS_VSCROLL)) != 0)
|
|
{
|
|
::SetScrollRange(pView->m_hWnd, SB_HORZ, 0, 0, TRUE);
|
|
::SetScrollRange(pView->m_hWnd, SB_VERT, 0, 0, TRUE);
|
|
}
|
|
|
|
// restore old 3D style
|
|
pView->ModifyStyleEx(0, m_dwOrigStyleEx & WS_EX_CLIENTEDGE,
|
|
SWP_DRAWFRAME);
|
|
|
|
// force recalc layout on splitter window
|
|
CSplitterWnd* pSplitter = CView::GetParentSplitter(pView, TRUE);
|
|
if (pSplitter != NULL)
|
|
pSplitter->RecalcLayout();
|
|
}
|
|
|
|
// no active view or document during destroy
|
|
pFrameWnd->SetActiveView(NULL);
|
|
|
|
// destroy in-place frame window
|
|
pFrameWnd->DestroyWindow();
|
|
}
|
|
|
|
void COleServerDoc::ConnectView(CWnd* pParentWnd, CView* pView)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT_VALID(pParentWnd);
|
|
ASSERT_VALID(pView);
|
|
|
|
// move the view to the new parent
|
|
pView->SetParent(pParentWnd);
|
|
|
|
// Note: The currently active view on the original frame window is
|
|
// kept active, because some controls, especially Windows controls,
|
|
// continue to send notification messages to the original parent
|
|
// window of the control. So, the original frame window is kept
|
|
// alive with the original active view pointer intact, such that
|
|
// these notification messages do not get lost.
|
|
|
|
// set the active view of the new frame to newly moved view
|
|
CFrameWnd* pFrameWnd = pParentWnd->IsFrameWnd() ?
|
|
(CFrameWnd*)pParentWnd : pParentWnd->GetParentFrame();
|
|
pFrameWnd->SetActiveView(pView, FALSE);
|
|
pFrameWnd->RecalcLayout();
|
|
}
|
|
|
|
void COleServerDoc::OnFrameWindowActivate(BOOL bActivate)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
CFrameWnd* pFrameWnd = m_pInPlaceFrame;
|
|
ASSERT_VALID(pFrameWnd);
|
|
|
|
CWinThread* pThread = AfxGetThread();
|
|
if (bActivate)
|
|
{
|
|
// activating -- so set the main window
|
|
pThread->m_pActiveWnd = pFrameWnd;
|
|
|
|
// send activation notification messages
|
|
pFrameWnd->SendMessage(WM_ACTIVATEAPP, (WPARAM)TRUE);
|
|
pFrameWnd->SendMessage(WM_ACTIVATE, WA_ACTIVE);
|
|
}
|
|
else if (pFrameWnd == pThread->m_pActiveWnd)
|
|
{
|
|
// send deactivation notification messages
|
|
pFrameWnd->SendMessage(WM_ACTIVATEAPP, (WPARAM)FALSE);
|
|
pFrameWnd->SendMessage(WM_ACTIVATE, WA_INACTIVE);
|
|
|
|
// simulate deactivation notification messages
|
|
CView* pActiveView = pFrameWnd->GetActiveView();
|
|
if (pActiveView != NULL)
|
|
pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
|
|
|
|
// deactivating and was previously active -- reset the main window
|
|
pThread->m_pActiveWnd = NULL;
|
|
}
|
|
}
|
|
|
|
void COleServerDoc::OnDocWindowActivate(BOOL bActivate)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
CWinThread* pThread = AfxGetApp();
|
|
COleIPFrameWnd* pFrameWnd = m_pInPlaceFrame;
|
|
|
|
if (bActivate)
|
|
{
|
|
// attach frame windows back in the permanent map
|
|
pFrameWnd->m_pMainFrame->Attach(pFrameWnd->m_pMainFrame->Detach());
|
|
if (pFrameWnd->m_pDocFrame != NULL)
|
|
pFrameWnd->m_pDocFrame->Attach(pFrameWnd->m_pDocFrame->Detach());
|
|
|
|
// set active main window
|
|
pThread->m_pActiveWnd = pFrameWnd;
|
|
|
|
// show frame level controls
|
|
OnShowControlBars(pFrameWnd->m_pMainFrame, TRUE);
|
|
pFrameWnd->ShowOwnedWindows(TRUE);
|
|
|
|
// attempt toolbar negotiation
|
|
OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
|
|
|
|
// install the menu (also installs a hook which forwards messages from
|
|
// the menu to the inplace frame window)
|
|
pFrameWnd->m_lpFrame->SetMenu(
|
|
pFrameWnd->m_hSharedMenu, pFrameWnd->m_hOleMenu,
|
|
pFrameWnd->m_hWnd);
|
|
|
|
// set focus to the frame (it will probably set focus to the view)
|
|
// (by simulating normal application activate messages)
|
|
pFrameWnd->SendMessage(WM_ACTIVATE, WA_ACTIVE);
|
|
}
|
|
else
|
|
{
|
|
// clear active window for app if this object is active
|
|
if (pThread->m_pActiveWnd == pFrameWnd)
|
|
pThread->m_pActiveWnd = NULL;
|
|
|
|
// hide frame level controls -- this does not destroy them
|
|
pFrameWnd->ShowOwnedWindows(FALSE);
|
|
OnShowControlBars(pFrameWnd->m_pMainFrame, FALSE);
|
|
|
|
// attempt toolbar negotiation
|
|
OnResizeBorder(NULL, pFrameWnd->m_lpFrame, TRUE);
|
|
|
|
// simulate deactivation notification messages
|
|
CView* pActiveView = pFrameWnd->GetActiveView();
|
|
if (pActiveView != NULL)
|
|
pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
|
|
pFrameWnd->SendMessage(WM_ACTIVATE, WA_INACTIVE);
|
|
|
|
// set the m_hWnd members, but remove them from the maps
|
|
pFrameWnd->m_pMainFrame->m_hWnd = pFrameWnd->m_pMainFrame->Detach();
|
|
if (pFrameWnd->m_pDocFrame != NULL)
|
|
pFrameWnd->m_pDocFrame->m_hWnd = pFrameWnd->m_pDocFrame->Detach();
|
|
}
|
|
}
|
|
|
|
void COleServerDoc::OnShowControlBars(CFrameWnd* pFrameWnd, BOOL bShow)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(pFrameWnd == m_pInPlaceFrame->m_pMainFrame ||
|
|
pFrameWnd == m_pInPlaceFrame->m_pDocFrame);
|
|
ASSERT_VALID(pFrameWnd);
|
|
|
|
// show/hide all control bars
|
|
POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
// show/hide the next control bar
|
|
CControlBar* pBar =
|
|
(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
|
|
ASSERT_VALID(pBar);
|
|
if (bShow)
|
|
{
|
|
if (pBar->m_nStateFlags & CControlBar::tempHide)
|
|
{
|
|
pBar->m_nStateFlags &= ~CControlBar::tempHide;
|
|
pFrameWnd->ShowControlBar(pBar, bShow, TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pBar->IsVisible() && !pBar->IsFloating())
|
|
{
|
|
pBar->m_nStateFlags |= CControlBar::tempHide;
|
|
pFrameWnd->ShowControlBar(pBar, bShow, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void COleServerDoc::OnResizeBorder(
|
|
LPCRECT lpRectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL bFrame)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(lpRectBorder == NULL ||
|
|
AfxIsValidAddress(lpRectBorder, sizeof(RECT), FALSE));
|
|
ASSERT(lpUIWindow != NULL);
|
|
|
|
// use IOleInPlaceUIWindow::GetBorder if no border given
|
|
CRect rectBorder;
|
|
if (lpRectBorder != NULL)
|
|
{
|
|
// use border space passed in
|
|
rectBorder.CopyRect(lpRectBorder);
|
|
}
|
|
else
|
|
{
|
|
// GetBorderSpace may fail (WinWord6, for example)
|
|
if (lpUIWindow->GetBorder(&rectBorder) != S_OK)
|
|
{
|
|
// in that case, always call SetBorderSpace(NULL), but
|
|
// ignore the return value.
|
|
lpUIWindow->SetBorderSpace(NULL);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// get CWnd* for the OLE window
|
|
CFrameWnd* pFrameWnd = bFrame ?
|
|
m_pInPlaceFrame->m_pMainFrame : m_pInPlaceFrame->m_pDocFrame;
|
|
|
|
// if this is the active document clear temphide bits from bars
|
|
if (AfxGetThread()->m_pActiveWnd == m_pInPlaceFrame)
|
|
OnShowControlBars(pFrameWnd, TRUE);
|
|
|
|
// see how much space we need by calling reposition bars
|
|
CRect rectNeeded = rectBorder;
|
|
pFrameWnd->RepositionBars(0, 0xFFFF, 0, CWnd::reposQuery, &rectNeeded,
|
|
&rectBorder);
|
|
|
|
// request the border space from the container
|
|
CRect rectRequest(
|
|
rectNeeded.left - rectBorder.left,
|
|
rectNeeded.top - rectBorder.top,
|
|
rectBorder.right - rectNeeded.right,
|
|
rectBorder.bottom - rectNeeded.bottom);
|
|
CRect rectTemp;
|
|
rectTemp = rectRequest;
|
|
|
|
// if no border space, just call SetBorderSpace
|
|
if ((!rectRequest.IsRectNull() ||
|
|
!pFrameWnd->m_listControlBars.IsEmpty()) &&
|
|
lpUIWindow->RequestBorderSpace(&rectTemp) == S_OK)
|
|
{
|
|
// set the border space -- now this object owns it
|
|
VERIFY(lpUIWindow->SetBorderSpace(&rectRequest) == S_OK);
|
|
|
|
// move the bars into position after committing the space
|
|
pFrameWnd->RepositionBars(0, 0xFFFF, 0, CWnd::reposDefault, NULL,
|
|
&rectBorder);
|
|
|
|
// redraw all control bars
|
|
POSITION pos = pFrameWnd->m_listControlBars.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CControlBar* pBar =
|
|
(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos);
|
|
ASSERT_VALID(pBar);
|
|
if (!pBar->IsFloating())
|
|
pBar->UpdateWindow();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// hide any toolbars (since we couldn't get border space for any)
|
|
OnShowControlBars(pFrameWnd, FALSE);
|
|
|
|
// make sure border space is cleared
|
|
CRect rect(0,0,0,0);
|
|
lpUIWindow->SetBorderSpace(&rect);
|
|
}
|
|
}
|
|
|
|
void COleServerDoc::OnDeactivate()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
ASSERT(m_pInPlaceFrame != NULL);
|
|
|
|
// do UI deactivate first -- this hides everything
|
|
if (m_pInPlaceFrame->m_bUIActive)
|
|
{
|
|
OnDeactivateUI(FALSE);
|
|
|
|
// some containers call OnDeactivate during OnDeactivateUI
|
|
if (m_pInPlaceFrame == NULL)
|
|
return;
|
|
}
|
|
ASSERT(m_pInPlaceFrame != NULL);
|
|
ASSERT(!m_pInPlaceFrame->m_bUIActive);
|
|
|
|
// now safe to destroy the shared menu
|
|
m_pInPlaceFrame->DestroySharedMenu();
|
|
|
|
// no longer need doc & frame window interfaces
|
|
RELEASE(m_pInPlaceFrame->m_lpFrame);
|
|
RELEASE(m_pInPlaceFrame->m_lpDocFrame);
|
|
DestroyInPlaceFrame(m_pInPlaceFrame);
|
|
m_pInPlaceFrame = NULL;
|
|
// destructor for COleIPFrameWnd or derivative should cleanup any
|
|
// toolbars etc. created during in-place activation
|
|
|
|
// last of all, call IOleClientSite::InPlaceDeactivate
|
|
ASSERT(m_lpClientSite != NULL);
|
|
LPOLEINPLACESITE lpInPlaceSite =
|
|
QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
|
|
if (lpInPlaceSite != NULL)
|
|
{
|
|
lpInPlaceSite->OnInPlaceDeactivate();
|
|
lpInPlaceSite->Release();
|
|
}
|
|
}
|
|
|
|
void COleServerDoc::OnDeactivateUI(BOOL bUndoable)
|
|
{
|
|
ASSERT_VALID(this);
|
|
COleIPFrameWnd* pFrameWnd = m_pInPlaceFrame;
|
|
|
|
if (pFrameWnd == NULL || !pFrameWnd->m_bUIActive)
|
|
return;
|
|
|
|
// reset active object pointers
|
|
ASSERT(pFrameWnd->m_lpFrame != NULL);
|
|
pFrameWnd->m_lpFrame->SetActiveObject(NULL, NULL);
|
|
if (pFrameWnd->m_lpDocFrame != NULL)
|
|
pFrameWnd->m_lpDocFrame->SetActiveObject(NULL, NULL);
|
|
|
|
// remove frame & document level frame controls
|
|
ASSERT(pFrameWnd->m_lpFrame != NULL);
|
|
OnShowControlBars(pFrameWnd->m_pMainFrame, FALSE);
|
|
if (pFrameWnd->m_lpDocFrame != NULL)
|
|
OnShowControlBars(pFrameWnd->m_pDocFrame, FALSE);
|
|
|
|
// hide the frame and any popups owned by the frame
|
|
pFrameWnd->ShowOwnedWindows(FALSE);
|
|
pFrameWnd->ShowWindow(SW_HIDE);
|
|
pFrameWnd->m_nShowDelay = SW_HIDE;
|
|
pFrameWnd->m_pMainFrame->m_nShowDelay = SW_HIDE;
|
|
|
|
// set the m_hWnd members, but remove them from the maps
|
|
pFrameWnd->m_pMainFrame->m_hWnd = pFrameWnd->m_pMainFrame->Detach();
|
|
if (pFrameWnd->m_pDocFrame != NULL)
|
|
pFrameWnd->m_pDocFrame->m_hWnd = pFrameWnd->m_pDocFrame->Detach();
|
|
|
|
// no longer UI active...
|
|
pFrameWnd->m_bUIActive = FALSE;
|
|
CWinThread* pThread = AfxGetApp();
|
|
if (pThread->m_pActiveWnd == pFrameWnd)
|
|
pThread->m_pActiveWnd = NULL;
|
|
|
|
// call IOleClientSite::OnUIDeactivate
|
|
ASSERT(m_lpClientSite != NULL);
|
|
LPOLEINPLACESITE lpInPlaceSite =
|
|
QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
|
|
if (lpInPlaceSite != NULL)
|
|
{
|
|
lpInPlaceSite->OnUIDeactivate(bUndoable);
|
|
lpInPlaceSite->Release();
|
|
}
|
|
}
|
|
|
|
void COleServerDoc::OnSetItemRects(LPCRECT lpPosRect, LPCRECT lpClipRect)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
|
|
ASSERT(AfxIsValidAddress(lpClipRect, sizeof(RECT), FALSE));
|
|
|
|
if (m_pInPlaceFrame == NULL)
|
|
return;
|
|
ASSERT_VALID(m_pInPlaceFrame);
|
|
|
|
// tell the frame to position itself such that the view is at the given
|
|
// rectangle (relative to the frame's parent)
|
|
m_pInPlaceFrame->RepositionFrame(lpPosRect, lpClipRect);
|
|
}
|
|
|
|
BOOL COleServerDoc::OnReactivateAndUndo()
|
|
{
|
|
// default implementation doesn't support undo
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc special APIs for in-place editing
|
|
|
|
void COleServerDoc::RequestPositionChange(LPCRECT lpPosRect)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
|
|
|
|
// get IOleInPlaceSite interface
|
|
ASSERT(m_lpClientSite != NULL);
|
|
LPOLEINPLACESITE lpInPlaceSite =
|
|
QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
|
|
|
|
if (lpInPlaceSite != NULL)
|
|
{
|
|
// call IOleInPlaceSite::OnPosRectChange
|
|
lpInPlaceSite->OnPosRectChange(lpPosRect);
|
|
lpInPlaceSite->Release();
|
|
}
|
|
}
|
|
|
|
BOOL COleServerDoc::ScrollContainerBy(CSize sizeScroll)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// get IOleInPlaceSite interface
|
|
ASSERT(m_lpClientSite != NULL);
|
|
LPOLEINPLACESITE lpInPlaceSite =
|
|
QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
|
|
if (lpInPlaceSite == NULL)
|
|
return FALSE;
|
|
|
|
// call IOleInPlaceSite::Scroll
|
|
BOOL bResult = lpInPlaceSite->Scroll(sizeScroll) == S_OK;
|
|
lpInPlaceSite->Release();
|
|
return bResult;
|
|
}
|
|
|
|
BOOL COleServerDoc::DeactivateAndUndo()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// get IOleInPlaceSite interface
|
|
ASSERT(m_lpClientSite != NULL);
|
|
LPOLEINPLACESITE lpInPlaceSite =
|
|
QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
|
|
if (lpInPlaceSite == NULL)
|
|
return FALSE;
|
|
|
|
// call IOleInPlaceSite::DeactivateAndUndo
|
|
BOOL bResult = lpInPlaceSite->DeactivateAndUndo() == S_OK;
|
|
lpInPlaceSite->Release();
|
|
return bResult;
|
|
}
|
|
|
|
BOOL COleServerDoc::DiscardUndoState()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// get IOleInPlaceSite interface
|
|
ASSERT(m_lpClientSite != NULL);
|
|
LPOLEINPLACESITE lpInPlaceSite =
|
|
QUERYINTERFACE(m_lpClientSite, IOleInPlaceSite);
|
|
if (lpInPlaceSite == NULL)
|
|
return FALSE;
|
|
|
|
// call IOleInPlaceSite::DiscardUndoState
|
|
BOOL bResult = lpInPlaceSite->DiscardUndoState() == S_OK;
|
|
lpInPlaceSite->Release();
|
|
return bResult;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc OLE interface implementation
|
|
|
|
BEGIN_INTERFACE_MAP(COleServerDoc, COleLinkingDoc)
|
|
INTERFACE_PART(COleServerDoc, IID_IPersistStorage, PersistStorage)
|
|
INTERFACE_PART(COleServerDoc, IID_IOleObject, OleObject)
|
|
INTERFACE_PART(COleServerDoc, IID_IDataObject, DataObject)
|
|
INTERFACE_PART(COleServerDoc, IID_IOleWindow, OleInPlaceObject)
|
|
INTERFACE_PART(COleServerDoc, IID_IOleInPlaceObject, OleInPlaceObject)
|
|
INTERFACE_PART(COleServerDoc, IID_IOleInPlaceActiveObject, OleInPlaceActiveObject)
|
|
END_INTERFACE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc::CPersistStorage
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XPersistStorage::AddRef()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
|
|
return pThis->ExternalAddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XPersistStorage::Release()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
|
|
return pThis->ExternalRelease();
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XPersistStorage::QueryInterface(
|
|
REFIID iid, LPVOID* ppvObj)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
|
|
return pThis->ExternalQueryInterface(&iid, ppvObj);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XPersistStorage::GetClassID(LPCLSID lpClassID)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
|
|
|
|
LPPERSISTFILE lpPersistFile = (LPPERSISTFILE)
|
|
pThis->GetInterface(&IID_IPersistFile);
|
|
return lpPersistFile->GetClassID(lpClassID);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XPersistStorage::IsDirty()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
|
|
|
|
LPPERSISTFILE lpPersistFile = (LPPERSISTFILE)
|
|
pThis->GetInterface(&IID_IPersistFile);
|
|
return lpPersistFile->IsDirty();
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XPersistStorage::InitNew(LPSTORAGE pStg)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = S_OK;
|
|
TRY
|
|
{
|
|
// delegate to member function in the document
|
|
pThis->OnNewEmbedding(pStg);
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
ASSERT_VALID(pThis);
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XPersistStorage::Load(LPSTORAGE pStg)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = S_OK;
|
|
pThis->BeginDeferErrors();
|
|
TRY
|
|
{
|
|
// delegate to member function in the document
|
|
pThis->OnOpenEmbedding(pStg);
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
sc = pThis->EndDeferErrors(sc);
|
|
|
|
ASSERT_VALID(pThis);
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XPersistStorage::Save(
|
|
LPSTORAGE pStgSave, BOOL fSameAsLoad)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
|
|
ASSERT_VALID(pThis);
|
|
|
|
// don't bother saving if destination is up-to-date
|
|
if (fSameAsLoad && !pThis->IsModified())
|
|
return S_OK;
|
|
|
|
SCODE sc = S_OK;
|
|
pThis->BeginDeferErrors();
|
|
TRY
|
|
{
|
|
// delegate through the document
|
|
ASSERT(pThis->m_bRemember);
|
|
pThis->m_bRemember = FALSE;
|
|
pThis->m_bSameAsLoad = fSameAsLoad;
|
|
pThis->OnSaveEmbedding(pStgSave);
|
|
|
|
// clear dirty flag since save to same storage successful
|
|
if (fSameAsLoad)
|
|
{
|
|
pThis->SetModifiedFlag(FALSE);
|
|
|
|
// notify clients that object has been saved
|
|
pThis->NotifySaved();
|
|
}
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
sc = pThis->EndDeferErrors(sc);
|
|
|
|
// restore default state
|
|
pThis->m_bRemember = TRUE;
|
|
|
|
ASSERT_VALID(pThis);
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XPersistStorage::SaveCompleted(LPSTORAGE pStgSaved)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, PersistStorage)
|
|
ASSERT_VALID(pThis);
|
|
|
|
// call SaveCompleted on any embedded items
|
|
pThis->CommitItems(pStgSaved != NULL);
|
|
|
|
// update state to reflect new storage
|
|
if (pStgSaved != NULL)
|
|
{
|
|
// attach new storage
|
|
pStgSaved->AddRef();
|
|
RELEASE(pThis->m_lpRootStg);
|
|
pThis->m_lpRootStg = pStgSaved;
|
|
|
|
// now this document is storage based
|
|
pThis->m_strPathName.Empty();
|
|
pThis->m_bEmbedded = TRUE;
|
|
pThis->SetModifiedFlag(FALSE);
|
|
|
|
// notify clients that object has been saved
|
|
pThis->NotifySaved();
|
|
}
|
|
|
|
ASSERT_VALID(pThis);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XPersistStorage::HandsOffStorage()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, PersistStorage)
|
|
|
|
if (pThis->m_lpRootStg != NULL)
|
|
{
|
|
// first call HandsOffStorage for all the embedded client items
|
|
POSITION pos = pThis->GetStartPosition();
|
|
COleClientItem* pItem;
|
|
while ((pItem = pThis->GetNextClientItem(pos)) != NULL)
|
|
{
|
|
ASSERT(pItem->m_lpObject != NULL);
|
|
LPPERSISTSTORAGE lpPersistStorage =
|
|
QUERYINTERFACE(pItem->m_lpObject, IPersistStorage);
|
|
ASSERT(lpPersistStorage != NULL);
|
|
lpPersistStorage->HandsOffStorage();
|
|
lpPersistStorage->Release();
|
|
}
|
|
|
|
// for now, can't access the storage
|
|
RELEASE(pThis->m_lpRootStg);
|
|
}
|
|
|
|
ASSERT_VALID(pThis);
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc::XOleObject
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XOleObject::AddRef()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
return pThis->ExternalAddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XOleObject::Release()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
return pThis->ExternalRelease();
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::QueryInterface(
|
|
REFIID iid, LPVOID* ppvObj)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
return pThis->ExternalQueryInterface(&iid, ppvObj);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::SetClientSite(
|
|
LPOLECLIENTSITE pClientSite)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
// maintain reference counts
|
|
if (pClientSite != NULL)
|
|
pClientSite->AddRef();
|
|
RELEASE(pThis->m_lpClientSite);
|
|
pThis->m_lpClientSite = pClientSite;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::GetClientSite(
|
|
LPOLECLIENTSITE* ppClientSite)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
if (pThis->m_lpClientSite == NULL)
|
|
{
|
|
*ppClientSite = NULL;
|
|
return E_FAIL;
|
|
}
|
|
|
|
*ppClientSite = pThis->m_lpClientSite;
|
|
pThis->m_lpClientSite->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::SetHostNames(
|
|
LPCOLESTR lpszContainerApp, LPCOLESTR lpszContainerObj)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
USES_CONVERSION;
|
|
|
|
TRY
|
|
{
|
|
pThis->OnSetHostNames(OLE2CT(lpszContainerApp),
|
|
OLE2CT(lpszContainerObj));
|
|
}
|
|
END_TRY
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::Close(DWORD dwSaveOption)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
pThis->InternalAddRef(); // protect this object
|
|
|
|
SCODE sc = S_OK;
|
|
TRY
|
|
{
|
|
// delegate through document for most of the work
|
|
pThis->OnClose((OLECLOSE)dwSaveOption);
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
pThis->InternalRelease(); // may 'delete this'
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::SetMoniker(
|
|
DWORD /*dwWhichMoniker*/, LPMONIKER /*pmk*/)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
if (pThis->m_lpClientSite == NULL)
|
|
return E_FAIL;
|
|
|
|
// get current full moniker from client-site
|
|
LPMONIKER lpMoniker = NULL;
|
|
if (pThis->m_lpClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
|
|
OLEWHICHMK_OBJFULL, &lpMoniker) != S_OK)
|
|
{
|
|
// just to make sure -- always set moniker to NULL on failure
|
|
lpMoniker = NULL;
|
|
}
|
|
|
|
// update all embedded items with new moniker
|
|
POSITION pos = pThis->GetStartPosition();
|
|
COleClientItem* pItem;
|
|
while ((pItem = pThis->GetNextClientItem(pos)) != NULL)
|
|
{
|
|
if (pItem->m_bMoniker)
|
|
pItem->m_lpObject->SetMoniker(OLEWHICHMK_CONTAINER, lpMoniker);
|
|
}
|
|
|
|
// send Rename advises
|
|
pThis->NotifyAllItems(OLE_RENAMED, (DWORD)lpMoniker);
|
|
RELEASE(lpMoniker);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::GetMoniker(
|
|
DWORD dwAssign, DWORD /*dwWhichMoniker*/, LPMONIKER* ppMoniker)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
*ppMoniker = pThis->GetMoniker((OLEGETMONIKER)dwAssign);
|
|
return *ppMoniker == NULL ? E_FAIL : S_OK;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::InitFromData(
|
|
LPDATAOBJECT pDataObject, BOOL fCreation, DWORD /*dwReserved*/)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc;
|
|
TRY
|
|
{
|
|
// delegate through item
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
|
|
COleDataObject dataObject;
|
|
dataObject.Attach(pDataObject, FALSE);
|
|
sc = pItem->OnInitFromData(&dataObject, fCreation) ? S_OK : S_FALSE;
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::GetClipboardData(
|
|
DWORD /*dwReserved*/, LPDATAOBJECT* ppDataObject)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
*ppDataObject = NULL;
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = S_OK;
|
|
TRY
|
|
{
|
|
// delegate through item
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
|
|
COleDataSource* pDataSource =
|
|
pItem->OnGetClipboardData(TRUE, NULL, NULL);
|
|
ASSERT(pDataSource != NULL);
|
|
|
|
*ppDataObject =
|
|
(LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject);
|
|
ASSERT(*ppDataObject != NULL);
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::DoVerb(
|
|
LONG iVerb, LPMSG /*lpmsg*/, LPOLECLIENTSITE /*pActiveSite*/, LONG /*lindex*/,
|
|
HWND /*hwndParent*/, LPCRECT /*lpPosRect*/)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
pThis->InternalAddRef(); // protect this object
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = S_OK;
|
|
TRY
|
|
{
|
|
// delegate through item
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
pItem->OnDoVerb(iVerb);
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
pThis->InternalRelease(); // may 'delete this'
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::EnumVerbs(
|
|
IEnumOLEVERB** ppenumOleVerb)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
*ppenumOleVerb = NULL;
|
|
|
|
LPOLEOBJECT lpObject = (LPOLEOBJECT)pThis->GetInterface(&IID_IOleObject);
|
|
ASSERT(lpObject != NULL);
|
|
CLSID clsid;
|
|
lpObject->GetUserClassID(&clsid);
|
|
|
|
return OleRegEnumVerbs(clsid, ppenumOleVerb);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::Update()
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = S_OK;
|
|
TRY
|
|
{
|
|
// delegate through item
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
pItem->OnUpdateItems();
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::IsUpToDate()
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc;
|
|
TRY
|
|
{
|
|
// delegate through item
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
|
|
sc = pItem->OnQueryUpdateItems() ? S_FALSE : S_OK;
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::GetUserClassID(CLSID* lpClassID)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
LPPERSISTFILE lpPersistFile = (LPPERSISTFILE)
|
|
pThis->GetInterface(&IID_IPersistFile);
|
|
return lpPersistFile->GetClassID(lpClassID);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::GetUserType(
|
|
DWORD dwFormOfType, LPOLESTR* ppszUserType)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
*ppszUserType = NULL;
|
|
|
|
LPOLEOBJECT lpObject = (LPOLEOBJECT)pThis->GetInterface(&IID_IOleObject);
|
|
ASSERT(lpObject != NULL);
|
|
CLSID clsid;
|
|
lpObject->GetUserClassID(&clsid);
|
|
|
|
return OleRegGetUserType(clsid, dwFormOfType, ppszUserType);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::SetExtent(
|
|
DWORD dwDrawAspect, LPSIZEL lpsizel)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_FAIL;
|
|
TRY
|
|
{
|
|
// convert rectangle to a CSize and call item OnSetExtent
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
|
|
CSize size((int)lpsizel->cx, (int)lpsizel->cy);
|
|
if (pItem->OnSetExtent((DVASPECT)dwDrawAspect, size))
|
|
sc = S_OK;
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::GetExtent(
|
|
DWORD dwDrawAspect, LPSIZEL lpsizel)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_INVALIDARG;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
|
|
// call to get regular windows CSize
|
|
CSize size;
|
|
if (pItem->OnGetExtent((DVASPECT)dwDrawAspect, size))
|
|
{
|
|
if (size.cy < 0)
|
|
size.cy = -size.cy; // extents are always positive
|
|
lpsizel->cx = size.cx;
|
|
lpsizel->cy = size.cy;
|
|
|
|
sc = S_OK;
|
|
}
|
|
}
|
|
CATCH_ALL(e)
|
|
{
|
|
sc = COleException::Process(e);
|
|
DELETE_EXCEPTION(e);
|
|
}
|
|
END_CATCH_ALL
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::Advise(
|
|
IAdviseSink* pAdvSink, DWORD* pdwConnection)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetOleObject()->Advise(pAdvSink, pdwConnection);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::Unadvise(DWORD dwConnection)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetOleObject()->Unadvise(dwConnection);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::EnumAdvise(
|
|
LPENUMSTATDATA* ppenumAdvise)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetOleObject()->EnumAdvise(ppenumAdvise);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::GetMiscStatus(
|
|
DWORD dwAspect, DWORD* pdwStatus)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleObject)
|
|
|
|
*pdwStatus = 0;
|
|
|
|
LPOLEOBJECT lpObject = (LPOLEOBJECT)pThis->GetInterface(&IID_IOleObject);
|
|
ASSERT(lpObject != NULL);
|
|
CLSID clsid;
|
|
lpObject->GetUserClassID(&clsid);
|
|
|
|
return OleRegGetMiscStatus(clsid, dwAspect, pdwStatus);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleObject::SetColorScheme(LPLOGPALETTE lpLogpal)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_NOTIMPL;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
|
|
// delegate to embedded item
|
|
if (pItem->OnSetColorScheme(lpLogpal))
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
return sc;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc::XDataObject
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XDataObject::AddRef()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
return pThis->ExternalAddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XDataObject::Release()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
return pThis->ExternalRelease();
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::QueryInterface(
|
|
REFIID iid, LPVOID* ppvObj)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
return pThis->ExternalQueryInterface(&iid, ppvObj);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::GetData(
|
|
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetDataObject()->GetData(lpFormatEtc, lpStgMedium);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::GetDataHere(
|
|
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetDataObject()->GetDataHere(lpFormatEtc, lpStgMedium);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::QueryGetData(
|
|
LPFORMATETC lpFormatEtc)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetDataObject()->QueryGetData(lpFormatEtc);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::GetCanonicalFormatEtc(
|
|
LPFORMATETC /*lpFormatEtcIn*/, LPFORMATETC /*lpFormatEtcOut*/)
|
|
{
|
|
// because we support the target-device (ptd) for server metafile format,
|
|
// all members of the FORMATETC are significant.
|
|
|
|
return DATA_S_SAMEFORMATETC;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::SetData(
|
|
LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetDataObject()->SetData(lpFormatEtc, lpStgMedium, bRelease);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::EnumFormatEtc(
|
|
DWORD dwDirection, LPENUMFORMATETC* ppenumFormatEtc)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetDataObject()->EnumFormatEtc(dwDirection, ppenumFormatEtc);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::DAdvise(
|
|
FORMATETC* pFormatetc, DWORD advf,
|
|
LPADVISESINK pAdvSink, DWORD* pdwConnection)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetDataObject()->DAdvise(pFormatetc, advf, pAdvSink,
|
|
pdwConnection);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::DUnadvise(DWORD dwConnection)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetDataObject()->DUnadvise(dwConnection);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XDataObject::EnumDAdvise(
|
|
LPENUMSTATDATA* ppenumAdvise)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, DataObject)
|
|
|
|
COleServerItem* pItem;
|
|
SCODE sc = E_OUTOFMEMORY;
|
|
TRY
|
|
{
|
|
pItem = pThis->GetEmbeddedItem();
|
|
ASSERT_VALID(pItem);
|
|
ASSERT_KINDOF(COleServerItem, pItem);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
if (sc != S_OK)
|
|
return sc;
|
|
|
|
return pItem->GetDataObject()->EnumDAdvise(ppenumAdvise);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc::COleInPlaceObject
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceObject::AddRef()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
|
|
return pThis->ExternalAddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceObject::Release()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
|
|
return pThis->ExternalRelease();
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceObject::QueryInterface(
|
|
REFIID iid, LPVOID* ppvObj)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
|
|
return pThis->ExternalQueryInterface(&iid, ppvObj);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceObject::GetWindow(HWND* lphwnd)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
|
|
|
|
LPOLEINPLACEACTIVEOBJECT lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
|
|
pThis->GetInterface(&IID_IOleInPlaceActiveObject);
|
|
return lpActiveObject->GetWindow(lphwnd);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceObject::ContextSensitiveHelp(
|
|
BOOL fEnterMode)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceObject)
|
|
|
|
LPOLEINPLACEACTIVEOBJECT lpActiveObject = (LPOLEINPLACEACTIVEOBJECT)
|
|
pThis->GetInterface(&IID_IOleInPlaceActiveObject);
|
|
return lpActiveObject->ContextSensitiveHelp(fEnterMode);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceObject::InPlaceDeactivate()
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
pThis->InternalAddRef(); // protect this object
|
|
|
|
SCODE sc = E_UNEXPECTED;
|
|
TRY
|
|
{
|
|
// only call deactivate if necessary
|
|
if (pThis->m_pInPlaceFrame != NULL)
|
|
pThis->OnDeactivate();
|
|
|
|
// should be completely inactive
|
|
ASSERT(pThis->m_pInPlaceFrame == NULL);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
pThis->InternalRelease(); // may 'delete this'
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceObject::UIDeactivate()
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
pThis->InternalAddRef(); // protect this object
|
|
|
|
SCODE sc = E_UNEXPECTED;
|
|
TRY
|
|
{
|
|
// only call OnUIDeactivate if necessary
|
|
if (pThis->m_pInPlaceFrame != NULL &&
|
|
pThis->m_pInPlaceFrame->m_bUIActive)
|
|
{
|
|
pThis->OnDeactivateUI(FALSE); // default to not undoable
|
|
}
|
|
|
|
// should not be ui active
|
|
ASSERT(pThis->m_pInPlaceFrame == NULL ||
|
|
!pThis->m_pInPlaceFrame->m_bUIActive);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
pThis->InternalRelease(); // may 'delete this'
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceObject::SetObjectRects(
|
|
LPCRECT lpPosRect, LPCRECT lpClipRect)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = E_UNEXPECTED;
|
|
TRY
|
|
{
|
|
pThis->OnSetItemRects(lpPosRect, lpClipRect);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceObject::ReactivateAndUndo()
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = E_UNEXPECTED;
|
|
TRY
|
|
{
|
|
sc = pThis->OnReactivateAndUndo() ? S_OK : INPLACE_E_NOTUNDOABLE;
|
|
}
|
|
END_TRY
|
|
|
|
return sc;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COleServerDoc::XOleInPlaceActiveObject
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceActiveObject::AddRef()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
|
|
return pThis->ExternalAddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COleServerDoc::XOleInPlaceActiveObject::Release()
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
|
|
return pThis->ExternalRelease();
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::QueryInterface(
|
|
REFIID iid, LPVOID* ppvObj)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
|
|
return pThis->ExternalQueryInterface(&iid, ppvObj);
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::GetWindow(
|
|
HWND* lphwnd)
|
|
{
|
|
METHOD_PROLOGUE_EX_(COleServerDoc, OleInPlaceActiveObject)
|
|
|
|
*lphwnd = pThis->m_pInPlaceFrame->GetSafeHwnd();
|
|
return *lphwnd != NULL ? S_OK : E_FAIL;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::ContextSensitiveHelp(
|
|
BOOL fEnterMode)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
if (fEnterMode)
|
|
{
|
|
if (!pThis->m_pInPlaceFrame->m_bHelpMode)
|
|
{
|
|
// check if help mode probable
|
|
if (!pThis->m_pInPlaceFrame->CanEnterHelpMode())
|
|
return E_UNEXPECTED;
|
|
|
|
// attempt to enter context help
|
|
if (!pThis->m_pInPlaceFrame->PostMessage(WM_COMMAND, ID_CONTEXT_HELP))
|
|
return E_UNEXPECTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// just exit help mode
|
|
pThis->m_pInPlaceFrame->ExitHelpMode();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::TranslateAccelerator(
|
|
LPMSG lpmsg)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
pThis->InternalAddRef(); // protect this object
|
|
|
|
SCODE sc = E_UNEXPECTED;
|
|
TRY
|
|
{
|
|
// get frame window for this document
|
|
CFrameWnd* pFrameWnd = pThis->m_pInPlaceFrame;
|
|
ASSERT_VALID(pFrameWnd);
|
|
|
|
// attempt translate accelerator
|
|
MSG msg = *lpmsg;
|
|
sc = pFrameWnd->PreTranslateMessage(&msg) ? S_OK : S_FALSE;
|
|
*lpmsg = msg;
|
|
}
|
|
END_TRY
|
|
|
|
pThis->InternalRelease(); // may 'delete this'
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::OnFrameWindowActivate(
|
|
BOOL fActivate)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = E_UNEXPECTED;
|
|
TRY
|
|
{
|
|
pThis->OnFrameWindowActivate(fActivate);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::OnDocWindowActivate(
|
|
BOOL fActivate)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = E_UNEXPECTED;
|
|
TRY
|
|
{
|
|
pThis->OnDocWindowActivate(fActivate);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::ResizeBorder(
|
|
LPCRECT lprectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL fFrameWindow)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = E_UNEXPECTED;
|
|
TRY
|
|
{
|
|
pThis->OnResizeBorder(lprectBorder, lpUIWindow, fFrameWindow);
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
return sc;
|
|
}
|
|
|
|
STDMETHODIMP COleServerDoc::XOleInPlaceActiveObject::EnableModeless(
|
|
BOOL fEnable)
|
|
{
|
|
METHOD_PROLOGUE_EX(COleServerDoc, OleInPlaceActiveObject)
|
|
ASSERT_VALID(pThis);
|
|
|
|
SCODE sc = E_UNEXPECTED;
|
|
TRY
|
|
{
|
|
if (!fEnable)
|
|
{
|
|
// start modal state if not in modal state
|
|
if (!pThis->m_pInPlaceFrame->InModalState())
|
|
{
|
|
CWnd* pTemp = pThis->m_pInPlaceFrame->GetTopLevelParent();
|
|
BOOL bEnabled = pTemp->IsWindowEnabled();
|
|
pThis->m_pInPlaceFrame->BeginModalState();
|
|
pTemp->EnableWindow(bEnabled);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// end modal state if in modal state
|
|
if (pThis->m_pInPlaceFrame->InModalState())
|
|
pThis->m_pInPlaceFrame->EndModalState();
|
|
}
|
|
sc = S_OK;
|
|
}
|
|
END_TRY
|
|
|
|
return sc;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Diagnostics
|
|
|
|
#ifdef _DEBUG
|
|
void COleServerDoc::AssertValid() const
|
|
{
|
|
COleLinkingDoc::AssertValid();
|
|
if (m_pInPlaceFrame != NULL)
|
|
m_pInPlaceFrame->AssertValid();
|
|
if (m_pOrigParent != NULL)
|
|
m_pOrigParent->AssertValid();
|
|
}
|
|
|
|
void COleServerDoc::Dump(CDumpContext& dc) const
|
|
{
|
|
COleLinkingDoc::Dump(dc);
|
|
|
|
if (dc.GetDepth() != 0)
|
|
{
|
|
if (m_pInPlaceFrame != NULL)
|
|
dc << "\nwith in-place frame: " << m_pInPlaceFrame;
|
|
else
|
|
dc << "\nwith no in-place frame\n";
|
|
if (m_pOrigParent != NULL)
|
|
dc << "\nwith original parent: " << m_pOrigParent;
|
|
else
|
|
dc << "with no original parent\n";
|
|
}
|
|
dc << "m_lpClientSite = " << m_lpClientSite;
|
|
dc << "\nm_strHostObj = " << m_strHostObj;
|
|
dc << "\nm_bCntrVisible = " << m_bCntrVisible;
|
|
dc << "\nm_dwOrigStyle = " << m_dwOrigStyle;
|
|
|
|
dc << "\n";
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Inline function declarations expanded out-of-line
|
|
|
|
#ifndef _AFX_ENABLE_INLINES
|
|
|
|
// expand inlines for OLE server APIs
|
|
static char _szAfxOleInl[] = "afxole.inl";
|
|
#undef THIS_FILE
|
|
#define THIS_FILE _szAfxOleInl
|
|
#define _AFXOLESVR_INLINE
|
|
#include "afxole.inl"
|
|
|
|
#endif //!_AFX_ENABLE_INLINES
|
|
|
|
#ifdef AFX_INIT_SEG
|
|
#pragma code_seg(AFX_INIT_SEG)
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC(COleServerDoc, COleLinkingDoc)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|