Solved

CArchived CDocument -> Structured Storage

Posted on 1998-04-07
8
912 Views
Last Modified: 2013-11-20
I've got an SDI whose CDocument I'd like to break apart using structured storage.  I think that I need to use COleStreamFile, but I can't find any examples of how to break apart the document's variables into different streams.  (This is possible, right?)  My question is really for a referral: Besides Kruglinski, can anyone point me in the direction of sample code/explanations which demonstrate how to do this?  For bonus points, anyone have a snippet?  Thanks for any help.  
0
Comment
Question by:mweagle
  • 4
  • 4
8 Comments
 
LVL 10

Accepted Solution

by:
RONSLOW earned 170 total points
ID: 1317536
Do you want document properties in separate streams?  I have sample code for that if you want.

Also here is some sample code to serialize a CObject derived object to/from a stream.  You would call this in your SaveToStorage/ReadFromStorage functions of your document and pass m_lpRootStg as the lpRootStg param.

bool CMyObject::WriteToStorage(LPSTORAGE lpRootStg, LPCTSTR szName) {
      COleStreamFile file;
      CFileException fe;
      if (!file.CreateStream(lpRootStg, szName,
            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 = NULL;
      saveArchive.m_bForceFlat = FALSE;
      TRY
      {
            Serialize(saveArchive);
            saveArchive.Close();
            file.Close();
            
            // commit the root storage
            SCODE sc = 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
            saveArchive.Abort();
            THROW_LAST();
      }
      END_CATCH_ALL;
      return true;
}

bool CMyObject::ReadFromStorage(LPSTORAGE lpRootStg, LPCTSTR szName) {
      // open stream
      COleStreamFile file;
      CFileException fe;
      if (!file.OpenStream(lpRootStg, szName, CFile::modeRead|CFile::shareExclusive, &fe)) {
            QSchema::SetSchemaDirect(21);      // last schema without schema support
            if (fe.m_cause == CFileException::fileNotFound) {
                  return false;
            } 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 = NULL;
      loadArchive.m_bForceFlat = FALSE;
      TRY
      {
            Serialize(loadArchive);     // load main contents
            loadArchive.Close();
            file.Close();
      }
      CATCH_ALL(e)
      {
            file.Abort();   // will not throw an exception
            // DeleteContents();   // removed failed contents
            loadArchive.Abort();
            THROW_LAST();
      }
      END_CATCH_ALL;
      return true;
}



0
 

Author Comment

by:mweagle
ID: 1317537
This is exactly the kind of thing I'm looking for.  I have something like this:
CMyDocument:public CDocument
{
...
CMyBigObject1 m_object1;
CMyBigObject2 m_object2;
.
.
.
CMyBigObjectN m_objectN;
...}

Each CMyBigObjectN type has multiple CObLists and other variable storage types and so I'd like to break each CMyBigObjectN into a different stream so I don't have to read in the whole file.  Is this what you mean when you ask about document properties in different streams?  If it is, I'd really like to see your code.  Thanks for the help.  

0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1317538
I mean that I write out OLE document properties to the approriate stream (as opposed to the "content" stream that MFC writes your serialized data to).  I also write out (using the code above) my own data stored in a heirachy of lists.

What I would do for your code is
void CMyDocument::SaveToStorage(CObject* pObject) {
      m_object1.WriteToStorage(m_lpRootStg,"Object1");
      m_object2.WriteToStorage(m_lpRootStg,"Object2");
      ...
      m_objectN.WriteToStorage(m_lpRootStg,"ObjectN");
      CDocument::SaveToStorage(pObject);
}

where WriteToStorage method for each object is as per my answer above.  You simply use the same Serialize method as you'd use for standard MFC serializing.

Similar for reading from storage.  Of course, for reading, you don't need to read all the storages in, nor in the same order that you wrote them as each is independant.

0
 

Author Comment

by:mweagle
ID: 1317539
Great, I think that will solve the problem.  Sorry for my slowness (OLE is uncharted ground for me), but I have two related ?s if you don't mind.

(1) What is pObject in SaveToStorage?; and
(2) What is going on in CDocument::SaveToStorage(pObject)?  Is this a COleDocument call?  I searched MSDN but didn't find the function.

I wish VC5's docs were as clear as your explanation :)  Alas, they often are not, so now I'm off to amazon to find a good intro book on COM.  I need a bigger bookshelf.  Thanks again.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 10

Expert Comment

by:RONSLOW
ID: 1317540
pObject is usually NULL (if you want to save the whole document) - but COleServerItem also uses this to save itself, in which case it calls the SaveToStorage of its associated document and passes itself (this) as the pObject to the document.

Yes - SaveToStorage is an (undocumented) COleDocument function and is called by OnSaveDocument to do the saving.  The default implementation is very much like my code above but is hard coded to write to the stream "Contents".  I simply took the MFC code and changed it a little to allow me to write to a nominated stream.

Look in the MFC source to see how it is called (that's what I did).

A COM book may not help much with MFC environment .. they are usually straight C++

0
 

Author Comment

by:mweagle
ID: 1317541
Good thing mail interrupts IE4 (you saved me some money).  I now just need to change CMyDocument's base class to COleDocument and I've solved a problem I should have foreseen in the planning stage.  (The worst kind.)

If not COM, could you recommend a book on OLE & MFC?  Or is the MFC source sufficient for this problem?
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1317542
I haven't read many book on OLE/MFC - I do have a book on COM and have attended some seminars on COM.  Most of what I know comes from reading the docco, then looking at source code an smaples to work out what the docs really meant and find out how they work.

So, I cannot really recommend a book for you.

But the MFC source was sufficient for me as I just looked at the source code to see how files were saved to OLE structured storage and adapted what I needed from there.

0
 

Author Comment

by:mweagle
ID: 1317543
OK, I'll do the same.  Thanks again for the answer.  
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
deburging in oracle form 12 89
Best tools for Backup and restore of Wordpress site 6 55
Change to event 1 103
Way to decrease size of apk file 9 46
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
As a trusted technology advisor to your customers you are likely getting the daily question of, ‘should I put this in the cloud?’ As customer demands for cloud services increases, companies will see a shift from traditional buying patterns to new…

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

25 Experts available now in Live!

Get 1:1 Help Now