⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 olesvr1.cpp

📁 vc6.0完整版
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#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
	m_pDocObjectServer = NULL;      // becomes non-NULL if DocObject support enabled
}

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);

	// release doc object manager, if any
	if (m_pDocObjectServer != NULL)
	{
		delete m_pDocObjectServer;
		m_pDocObjectServer = NULL;
	}

	// 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;
}

CDocObjectServer* COleServerDoc::GetDocObjectServer(LPOLEDOCUMENTSITE pDocSite)
{
	// by default, we're not DocObject enabled
	UNUSED_ALWAYS(pDocSite);
	return NULL;
}

HRESULT COleServerDoc::OnExecOleCmd(const GUID* pguidCmdGroup, DWORD nCmdID,
		DWORD nCmdExecOpt, VARIANTARG* pvarargIn, VARIANTARG* pvarargOut)
{
	UNUSED_ALWAYS(pguidCmdGroup);
	UNUSED_ALWAYS(nCmdID);
	UNUSED_ALWAYS(nCmdExecOpt);
	UNUSED_ALWAYS(pvarargIn);
	UNUSED_ALWAYS(pvarargOut);

	return E_NOTIMPL;
}

LPUNKNOWN COleServerDoc::GetInterfaceHook(const void* piid)
{
	LPUNKNOWN lpUnk = NULL;

	// are we Doc Object supporters?
	if (m_pDocObjectServer != NULL)
	{
		// don't be tricked into handing out a different IUnknown
		DWORD lData1 = ((IID*)piid)->Data1;
		BOOL bUnknown = ((DWORD*)&IID_IUnknown)[0] == lData1 &&
			((DWORD*)piid)[1] == ((DWORD*)&IID_IUnknown)[1] &&
			((DWORD*)piid)[2] == ((DWORD*)&IID_IUnknown)[2] &&
			((DWORD*)piid)[3] == ((DWORD*)&IID_IUnknown)[3];

		if (bUnknown)
			return NULL;

		lpUnk = m_pDocObjectServer->GetInterface(piid);
	}

	// failing that, try the base class
	if (lpUnk == NULL)
		lpUnk = COleLinkingDoc::GetInterfaceHook(piid);

	return lpUnk;
}

void COleServerDoc::ActivateDocObject()
{
	if (m_pDocObjectServer != NULL)
		m_pDocObjectServer->ActivateDocObject();
}

/////////////////////////////////////////////////////////////////////////////
// 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
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -