📄 oledoc1.cpp
字号:
{
// abort changes to the current docfile
RELEASE(m_lpRootStg);
// create new temporary docfile
LPSTORAGE lpStorage;
SCODE sc = ::StgCreateDocfile(NULL, STGM_DELETEONRELEASE|
STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_CREATE,
0, &lpStorage);
if (sc != S_OK)
return FALSE;
ASSERT(lpStorage != NULL);
m_lpRootStg = lpStorage;
}
return TRUE;
}
BOOL COleDocument::OnOpenDocument(LPCTSTR lpszPathName)
{
USES_CONVERSION;
ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
// just use default implementation if 'docfile' not enabled
if (!m_bCompoundFile && m_lpRootStg == NULL)
{
ASSERT(lpszPathName != NULL);
return CDocument::OnOpenDocument(lpszPathName);
}
if (IsModified())
TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");
// abort changes to current docfile
if (lpszPathName != NULL)
{
DeleteContents();
RELEASE(m_lpRootStg);
}
SetModifiedFlag(); // dirty during de-serialize
BOOL bResult = FALSE;
TRY
{
if (m_lpRootStg == NULL)
{
LPCOLESTR lpsz = T2COLE(lpszPathName);
// use STGM_CONVERT if necessary
SCODE sc;
LPSTORAGE lpStorage = NULL;
if (StgIsStorageFile(lpsz) == S_FALSE)
{
// convert existing storage file
sc = StgCreateDocfile(lpsz, STGM_READWRITE|
STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_CONVERT,
0, &lpStorage);
if (FAILED(sc) || lpStorage == NULL)
sc = StgCreateDocfile(lpsz, STGM_READ|
STGM_TRANSACTED|STGM_CONVERT, 0, &lpStorage);
}
else
{
// open new storage file
sc = StgOpenStorage(lpsz, NULL,
STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_DENY_WRITE,
0, 0, &lpStorage);
if (FAILED(sc) || lpStorage == NULL)
sc = StgOpenStorage(lpsz, NULL,
STGM_READ|STGM_TRANSACTED, 0, 0, &lpStorage);
}
if (FAILED(sc))
AfxThrowOleException(sc);
ASSERT(lpStorage != NULL);
m_lpRootStg = lpStorage;
}
// use helper to read document from storage
LoadFromStorage();
SetModifiedFlag(FALSE); // start off with unmodified
bResult = TRUE;
}
CATCH_ALL(e)
{
DeleteContents(); // removed failed contents
RELEASE(m_lpRootStg);
// if not file-based load, return exceptions to the caller
if (lpszPathName == NULL)
{
THROW_LAST();
ASSERT(FALSE); // not reached
}
TRY
{
ReportSaveLoadException(lpszPathName, e,
FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
}
END_TRY
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
return bResult;
}
BOOL COleDocument::OnSaveDocument(LPCTSTR lpszPathName)
// lpszPathName must be fully qualified
{
USES_CONVERSION;
ASSERT(lpszPathName == NULL || AfxIsValidString(lpszPathName));
// use default implementation if 'docfile' not enabled
if (!m_bCompoundFile && m_lpRootStg == NULL)
{
ASSERT(lpszPathName != NULL);
return CDocument::OnSaveDocument(lpszPathName);
}
LPSTORAGE lpOrigStg = NULL;
if (lpszPathName != NULL)
m_bSameAsLoad = AfxComparePath(m_strPathName, lpszPathName);
BOOL bResult = FALSE;
TRY
{
// open new root storage if necessary
if (lpszPathName != NULL && !m_bSameAsLoad)
{
// temporarily detach current storage
lpOrigStg = m_lpRootStg;
m_lpRootStg = NULL;
LPSTORAGE lpStorage;
SCODE sc = ::StgCreateDocfile(T2COLE(lpszPathName),
STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_CREATE,
0, &lpStorage);
if (sc != S_OK)
AfxThrowOleException(sc);
ASSERT(lpStorage != NULL);
m_lpRootStg = lpStorage;
}
ASSERT(m_lpRootStg != NULL);
// use helper to save to root storage
SaveToStorage();
if (lpszPathName != NULL)
{
// commit each of the items
CommitItems(m_bRemember && !m_bSameAsLoad);
// mark document as clean if remembering the storage
if (m_bRemember)
SetModifiedFlag(FALSE);
// remember correct storage or release save copy as storage
if (!m_bSameAsLoad)
{
if (m_bRemember)
{
// Save As case -- m_stgRoot is new storage, forget old storage
lpOrigStg->Release();
}
else
{
// Save Copy As case -- m_stgRoot should hook up to m_stgOrig.
m_lpRootStg->Release();
m_lpRootStg = lpOrigStg;
}
}
}
bResult = TRUE;
}
CATCH_ALL(e)
{
if (lpOrigStg != NULL)
{
// save as failed: abort new storage, and re-attach original
RELEASE(m_lpRootStg);
m_lpRootStg = lpOrigStg;
}
if (lpszPathName == NULL)
{
THROW_LAST();
ASSERT(FALSE); // not reached
}
TRY
{
ReportSaveLoadException(lpszPathName, e,
TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);
}
END_TRY
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
// cleanup
m_bSameAsLoad = TRUE;
m_bRemember = TRUE;
return bResult;
}
void COleDocument::OnCloseDocument()
{
// close the document without deleting the memory
BOOL bAutoDelete = m_bAutoDelete;
m_bAutoDelete = FALSE;
CDocument::OnCloseDocument();
// release storage since document has been closed
RELEASE(m_lpRootStg);
// delete the document if necessary
if (bAutoDelete)
delete this;
}
/////////////////////////////////////////////////////////////////////////////
// Helpers for saving to IStorage based files
// (these are used in the 'docfile' implementation as well as for servers)
void COleDocument::SaveToStorage(CObject* pObject)
{
ASSERT(m_lpRootStg != NULL);
// create Contents stream
COleStreamFile file;
CFileException fe;
if (!file.CreateStream(m_lpRootStg, _T("Contents"),
CFile::modeReadWrite|CFile::shareExclusive|CFile::modeCreate, &fe))
{
if (fe.m_cause == CFileException::fileNotFound)
AfxThrowArchiveException(CArchiveException::badSchema);
else
AfxThrowFileException(fe.m_cause, fe.m_lOsError);
}
// save to Contents stream
CArchive saveArchive(&file, CArchive::store | CArchive::bNoFlushOnDelete);
saveArchive.m_pDocument = this;
saveArchive.m_bForceFlat = FALSE;
TRY
{
// save the contents
if (pObject != NULL)
pObject->Serialize(saveArchive);
else
Serialize(saveArchive);
saveArchive.Close();
file.Close();
// commit the root storage
SCODE sc = m_lpRootStg->Commit(STGC_ONLYIFCURRENT);
if (sc != S_OK)
AfxThrowOleException(sc);
}
CATCH_ALL(e)
{
file.Abort(); // will not throw an exception
CommitItems(FALSE); // abort save in progress
NO_CPP_EXCEPTION(saveArchive.Abort());
THROW_LAST();
}
END_CATCH_ALL
}
void COleDocument::LoadFromStorage()
{
ASSERT(m_lpRootStg != NULL);
// open Contents stream
COleStreamFile file;
CFileException fe;
if (!file.OpenStream(m_lpRootStg, _T("Contents"),
CFile::modeRead|CFile::shareExclusive, &fe) &&
!file.CreateStream(m_lpRootStg, _T("Contents"),
CFile::modeRead|CFile::shareExclusive|CFile::modeCreate, &fe))
{
if (fe.m_cause == CFileException::fileNotFound)
AfxThrowArchiveException(CArchiveException::badSchema);
else
AfxThrowFileException(fe.m_cause, fe.m_lOsError);
}
// load it with CArchive (loads from Contents stream)
CArchive loadArchive(&file, CArchive::load | CArchive::bNoFlushOnDelete);
loadArchive.m_pDocument = this;
loadArchive.m_bForceFlat = FALSE;
TRY
{
if (file.GetLength() != 0)
Serialize(loadArchive); // load main contents
loadArchive.Close();
file.Close();
}
CATCH_ALL(e)
{
file.Abort(); // will not throw an exception
DeleteContents(); // removed failed contents
NO_CPP_EXCEPTION(loadArchive.Abort());
THROW_LAST();
}
END_CATCH_ALL
}
/////////////////////////////////////////////////////////////////////////////
// COleDocument diagnostics
#ifdef _DEBUG
void COleDocument::AssertValid() const
{
CDocument::AssertValid();
ASSERT(m_ptd == NULL || AfxIsValidAddress(m_ptd, (size_t)m_ptd->tdSize, FALSE));
ASSERT_VALID(&m_docItemList);
ASSERT(!m_bEmbedded || m_strPathName.IsEmpty());
}
void COleDocument::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
dc << "with " << m_docItemList.GetCount() << " doc items";
dc << "\nm_dwNextItemNumber = " << m_dwNextItemNumber;
dc << "\nm_bLastVisible = " << m_bLastVisible;
dc << "\nm_bEmbedded = " << m_bEmbedded;
dc << "\nm_lpRootStg = " << m_lpRootStg;
dc << "\nm_bSameAsLoad = " << m_bSameAsLoad;
dc << "\nm_bRemember = " << m_bRemember;
dc << "\nm_ptd = " << m_ptd;
dc << "\n";
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDocItem
CDocItem::CDocItem()
{
m_pDocument = NULL;
}
CDocItem::~CDocItem()
{
ASSERT(m_pDocument == NULL); // must be detached from document
}
void CDocItem::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ASSERT_VALID(m_pDocument);
// nothing to do, there is no data
}
else
{
// if no document connected yet, attach it from the archive
if (m_pDocument == NULL)
{
COleDocument* pContainerDoc = (COleDocument*)ar.m_pDocument;
ASSERT_VALID(pContainerDoc);
ASSERT_KINDOF(COleDocument, pContainerDoc);
pContainerDoc->AddItem(this);
ASSERT(pContainerDoc == m_pDocument);
}
}
// perform ASSERT_VALID at the end because COleServerItem::AssertValid
// checks the validity of the m_pDocument pointer
ASSERT_VALID(this);
}
BOOL CDocItem::IsBlank() const
{
// by default, a CDocItem is not blank. COleClientItem is sometimes blank!
// (a COleServerItem is blank by default)
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CDocItem diagnostics
#ifdef _DEBUG
void CDocItem::AssertValid() const
{
CObject::AssertValid();
if (m_pDocument != NULL)
m_pDocument->AssertValid();
}
void CDocItem::Dump(CDumpContext& dc) const
{
CCmdTarget::Dump(dc);
dc << "m_pDocument = " << (void*)m_pDocument;
dc << "\n";
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// Inline function declarations expanded out-of-line
#ifndef _AFX_ENABLE_INLINES
// expand inlines for OLE general APIs
static char _szAfxOleInl[] = "afxole.inl";
#undef THIS_FILE
#define THIS_FILE _szAfxOleInl
#define _AFXOLE_INLINE
#include "afxole.inl"
#endif //!_AFX_ENABLE_INLINES
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
IMPLEMENT_SERIAL(CDocItem, CCmdTarget, 0)
IMPLEMENT_DYNAMIC(COleDocument, CDocument)
// These IMPLEMENT_DYNAMICs here for .OBJ granularity reasons.
IMPLEMENT_DYNAMIC(COleClientItem, CDocItem)
IMPLEMENT_DYNAMIC(COleServerItem, CDocItem)
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -