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

📄 oledoc1.cpp

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

#include "stdafx.h"

#ifdef AFX_OLE_SEG
#pragma code_seg(AFX_OLE_SEG)
#endif

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define new DEBUG_NEW

/////////////////////////////////////////////////////////////////////////////
// COleDocument - enables both server and client

COleDocument::COleDocument()
{
	ASSERT(m_viewList.IsEmpty());
	ASSERT(m_docItemList.IsEmpty());

#ifdef _DEBUG
	// check for common mistake of not initializing OLE libraries before
	//  creating an OLE document.
	LPMALLOC lpMalloc = NULL;
	if (::CoGetMalloc(MEMCTX_TASK, &lpMalloc) != S_OK)
	{
		TRACE0("Warning: CoGetMalloc(MEMCTX_TASK, ...) failed --\n");
		TRACE0("\tperhaps AfxOleInit() has not been called.\n");
	}
	RELEASE(lpMalloc);
#endif

	m_dwNextItemNumber = 1; // item number for first item in document
	m_bLastVisible = FALSE;

	m_bRemember = TRUE;
	m_bSameAsLoad = TRUE;
	m_lpRootStg = NULL;
	m_ptd = NULL;       // default to screen target device
	m_bCompoundFile = FALSE;

	AfxOleLockApp();
}

COleDocument::~COleDocument()
{
	ASSERT_VALID(this);

#ifdef _DEBUG
	if (!m_docItemList.IsEmpty())
		TRACE1("Warning: destroying COleDocument with %d doc items.\n",
			m_docItemList.GetCount());
#endif

	// remove all doc-items from the list before shutting down the storage
	POSITION pos = GetStartPosition();
	while (pos != NULL)
	{
		CDocItem* pItem = GetNextItem(pos);
		ASSERT(pItem != NULL);
		delete pItem;
	}

	// release the hold on the document storage
	RELEASE(m_lpRootStg);
	CoTaskMemFree(m_ptd);

	AfxOleUnlockApp();
}

/////////////////////////////////////////////////////////////////////////////
// DocItem management

void COleDocument::AddItem(CDocItem* pItem)
{
	// don't do an ASSERT_VALID until after we've added it !
	ASSERT_KINDOF(CDocItem, pItem);

	ASSERT(pItem->m_pDocument == NULL);     // not yet initialized
	m_docItemList.AddTail(pItem);
	pItem->m_pDocument = this;

	ASSERT_VALID(pItem);    // now it must be valid
}

void COleDocument::RemoveItem(CDocItem* pItem)
{
	ASSERT_VALID(pItem);    // must be valid before detach
	ASSERT_KINDOF(CDocItem, pItem);
	ASSERT(pItem->m_pDocument == this);     // formerly attached

	ASSERT(m_docItemList.Find(pItem) != NULL);  // must be in list
	m_docItemList.RemoveAt(m_docItemList.Find(pItem));
	ASSERT(m_docItemList.Find(pItem) == NULL);  // must not be in list now
	pItem->m_pDocument = NULL;
}

POSITION COleDocument::GetStartPosition() const
{
	ASSERT_VALID(this);
	return m_docItemList.GetHeadPosition();
}

CDocItem* COleDocument::GetNextItem(POSITION& pos) const
{
	// handle special case of !pos -- makes enumeration code smaller
	if (pos == NULL)
		return NULL;

	// otherwise get next item from list
	ASSERT_VALID(this);
	CDocItem* pItem = (CDocItem*)m_docItemList.GetNext(pos);
	ASSERT(pItem != NULL);
	ASSERT_KINDOF(CDocItem, pItem);
	ASSERT(pItem->m_pDocument == this);     // must be ours
	return pItem;
}

CDocItem*
COleDocument::GetNextItemOfKind(POSITION& pos, CRuntimeClass* pClass) const
{
	while (pos != NULL)
	{
		CDocItem* pItem = GetNextItem(pos);
		ASSERT_VALID(pItem);
		if (pItem->IsKindOf(pClass))
			return pItem;
	}
	return NULL;    // no suitable item found
}

COleClientItem* COleDocument::GetNextClientItem(POSITION& pos) const
{
	COleClientItem *pItem =
		(COleClientItem*)GetNextItemOfKind(pos, RUNTIME_CLASS(COleClientItem));
	return pItem;
}

COleServerItem* COleDocument::GetNextServerItem(POSITION& pos) const
{
	COleServerItem *pItem =
		(COleServerItem*)GetNextItemOfKind(pos, RUNTIME_CLASS(COleServerItem));
	return pItem;
}

void COleDocument::DeleteContents()
{
	// deletes all COleClientItem objects in the doc item list
	//  (Note: doesn't touch server items or other docitems)

	POSITION pos = GetStartPosition();
	COleClientItem* pItem;
	while ((pItem = GetNextClientItem(pos)) != NULL)
	{
		if (pItem->m_lpObject != NULL)
		{
			pItem->Release(OLECLOSE_NOSAVE);    // release OLE object
			RemoveItem(pItem);  // disconnect from document
			pItem->InternalRelease();   // may 'delete pItem'
		}
	}
}

void COleDocument::SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU)
{
	USES_CONVERSION;

	CDocument::SetPathName(lpszPathName, bAddToMRU);

	// update all of the objects' host names
	POSITION pos = GetStartPosition();
	COleClientItem* pItem;
	while ((pItem = GetNextClientItem(pos)) != NULL)
	{
		// update that item's host names
		pItem->m_lpObject->SetHostNames(T2COLE(AfxGetAppName()),
			T2COLE(m_strTitle));
	}
}

void COleDocument::Serialize(CArchive& ar)
{
	ASSERT_VALID(this);

	// serialize all items in the doc item list
	if (ar.IsStoring())
	{
		DWORD dwCount = 0;
		POSITION pos = GetStartPosition();
		while (pos != NULL)
		{
			CDocItem* pDocItem = GetNextItem(pos);
			ASSERT_VALID(pDocItem);

			// only count non-blank ones
			if (!pDocItem->IsBlank())
				++dwCount;
		}
		ar << dwCount;  // write count of objects

		// serialize all the items in the list
		pos = GetStartPosition();
		while (pos != NULL)
		{
			CDocItem* pDocItem = GetNextItem(pos);
			ASSERT_VALID(pDocItem);

			// only write non-blank ones
			if (!pDocItem->IsBlank())
				ar << pDocItem;
		}
	}
	else
	{
		// read number of items in the file
		DWORD dwCount;
		ar >> dwCount;

		// read all of them into the list
		while (dwCount--)
		{
			CDocItem* pDocItem;
			ar >> pDocItem;     // as they are serialized, they are added!
		}
	}
}

void COleDocument::CommitItems(BOOL bSuccess)
{
	// special 'Commit' phase for COleClientItem items
	POSITION pos = GetStartPosition();
	COleClientItem* pItem;
	while ((pItem = GetNextClientItem(pos)) != NULL)
	{
		// calling CommitItem with FALSE causes the object to revert
		//  to the original storage.  Calling CommitItem TRUE causes
		//  the item to adopt the new storage created in the Serialize
		//  function.
		pItem->CommitItem(bSuccess);
	}
}

BOOL COleDocument::HasBlankItems() const
{
	ASSERT_VALID(this);

	POSITION pos = GetStartPosition();
	while (pos != NULL)
	{
		CDocItem* pDocItem = GetNextItem(pos);
		ASSERT_VALID(pDocItem);
		if (pDocItem->IsBlank())
			return TRUE;    // blank item found
	}
	return FALSE;   // no items found that were blank
}

void COleDocument::UpdateModifiedFlag()
{
	ASSERT_VALID(this);

	POSITION pos = GetStartPosition();
	COleClientItem* pItem;
	while ((pItem = GetNextClientItem(pos)) != NULL)
	{
		if (pItem->IsModified())
		{
			SetModifiedFlag();
			break;
		}
	}
}

void COleDocument::PreCloseFrame(CFrameWnd* pFrameArg)
{
	ASSERT_VALID(this);
	ASSERT_VALID(pFrameArg);

	// turn off redraw so the user doesn't see the deactivation happening
	BOOL bSetRedraw = FALSE;
	if (pFrameArg->GetStyle() & WS_VISIBLE)
	{
		pFrameArg->SendMessage(WM_SETREDRAW, (WPARAM)FALSE);
		bSetRedraw = TRUE;
	}

	// deactivate any inplace active items on this frame
	COleClientItem* pItem = GetInPlaceActiveItem(pFrameArg);
	if (pItem != NULL)
	{
		pItem->Deactivate();
		pItem->Close(OLECLOSE_NOSAVE);
	}

	// turn redraw back on
	if (bSetRedraw)
		pFrameArg->SendMessage(WM_SETREDRAW, (WPARAM)TRUE);

	// should not have any inplace active items
	ASSERT(GetInPlaceActiveItem(pFrameArg) == NULL);
}

BOOL COleDocument::SaveModified()
{
	// determine if necessary to discard changes
	if (::InSendMessage())
	{
		POSITION pos = GetStartPosition();
		COleClientItem* pItem;
		while ((pItem = GetNextClientItem(pos)) != NULL)
		{
			ASSERT(pItem->m_lpObject != NULL);
			SCODE sc = pItem->m_lpObject->IsUpToDate();
			if (sc != OLE_E_NOTRUNNING && FAILED(sc))
			{
				// inside inter-app SendMessage limits the user's choices
				CString name = m_strPathName;
				if (name.IsEmpty())
					VERIFY(name.LoadString(AFX_IDS_UNTITLED));

				CString prompt;
				AfxFormatString1(prompt, AFX_IDP_ASK_TO_DISCARD, name);
				return AfxMessageBox(prompt, MB_OKCANCEL|MB_DEFBUTTON2,
					AFX_IDP_ASK_TO_DISCARD) == IDOK;
			}
		}
	}

	// sometimes items change without a notification, so we have to
	//  update the document's modified flag before calling
	//  CDocument::SaveModified.
	UpdateModifiedFlag();

	return CDocument::SaveModified();
}

void COleDocument::OnShowViews(BOOL /*bVisible*/)
{
	// no default implementation
}

void COleDocument::OnIdle()
{
	ASSERT_VALID(this);

	// determine if any visible views are on this document
	BOOL bVisible = FALSE;
	POSITION pos = GetFirstViewPosition();
	while (pos != NULL)
	{
		CView* pView = GetNextView(pos);
		ASSERT_VALID(pView);
		CFrameWnd* pFrameWnd = pView->GetParentFrame();
		ASSERT_VALID(pFrameWnd);
		if (pFrameWnd->GetStyle() & WS_VISIBLE)
		{
			bVisible = TRUE;
			break;
		}
	}

	// when state has changed, call OnShowViews
	if (bVisible != m_bLastVisible)
	{
		OnShowViews(bVisible);
		m_bLastVisible = bVisible;
	}
}

/////////////////////////////////////////////////////////////////////////////
// COleDocument -> window mapping

CFrameWnd* COleDocument::GetFirstFrame()
{
	ASSERT_VALID(this);

	// get position of first view in the document
	POSITION pos = GetFirstViewPosition();

	// get view at that position
	CView* pView = GetNextView(pos);
	if (pView == NULL)
		return NULL;
	ASSERT_VALID(pView);

	// return the first frame window that is a parent of that view
	CFrameWnd* pFrameWnd = (CFrameWnd*)pView->GetParentFrame();
	ASSERT_VALID(pFrameWnd);
	ASSERT_KINDOF(CFrameWnd, pFrameWnd);
	return pFrameWnd;
}

/////////////////////////////////////////////////////////////////////////////
// COleDocument helpers

LPMONIKER COleDocument::GetMoniker(OLEGETMONIKER /*nAssign*/)
{
	USES_CONVERSION;

	ASSERT_VALID(this);

	// no moniker for untitled documents
	if (m_strPathName.IsEmpty())
		return NULL;

	// return file moniker based on current path name
	LPMONIKER lpMoniker;
	CreateFileMoniker(T2COLE(m_strPathName), &lpMoniker);
	return lpMoniker;
}

LPOLEITEMCONTAINER COleDocument::GetContainer()
{
	// COleDocument doesn't support IOleClientSite::GetContainer

	return NULL;
}

/////////////////////////////////////////////////////////////////////////////
// 'Compound File' enabling in COleDocument

BOOL COleDocument::OnNewDocument()
{
	// call base class, which destroys all items
	if (!CDocument::OnNewDocument())
		return FALSE;

	// for file-based compound files, need to create temporary file
	if (m_bCompoundFile && !m_bEmbedded)

⌨️ 快捷键说明

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