How to use CDocManager in CDocument OnSaveAs override ?
I have an SDI CRichEditView application with Doc/View architecture in which I have overridden the OnFileSave method in the CDocument class. I would like to use the CDocManager class to save the current document. After many hours of internet browsing and Visual Studio 2008 experimentation, I am turning to you in desparation.
I might add (without intending to mislead), that using the OnFileOpen method override presents no problem:
However, when I attempt to do something similar with OnFileSaveAs, I am unable to weave may way through the morass of documentation involving CDocManager and CArchive. The only progress that I have made is to discover that the CArchive::m_pDocument is NULL and I have not figured out how to set it to the current document. What follows below is one of many failed attempts:
length = GetModuleFileName(NULL, fname, 2048);
char szFilters= "All Files (*.*)|*.*||";
CFileDialog fileDialog (FALSE, "*.*", "*.*",
OFN_FILEMUSTEXIST| OFN_HIDEREADONLY | OFN_NOCHANGEDIR , szFilters, NULL);
fileDialog.m_ofn.lpstrInitialDir = fname;
//fileDialog.m_ofn.lpstrInitialDir = m_csServerDir.GetBuffer(0); m_csServerDir.ReleaseBuffer();
if( fileDialog.DoModal ()==IDOK )
m_csPathname = fileDialog.GetPathName();
m_csFilename = fileDialog.GetFileName();
CDocManager * pDocMgr = (CDocManager *)AfxGetApp()->m_pDocManager;
//CArchive ar(CFile *pFile, UINT nMode, int nBufSize = 4096, void *lpBuf = 0);
//CArchive ar(const CArchive &arSrc);
//POSITION pos = ar.m_pDocument->GetFirstViewPosition();
// from: http://msdn.microsoft.com/en-us/library/kz2bk3c2(v=VS.80).aspx
// The framework sets m_pDocument to the document being serialized when a user issues
// a File Open or Save command. If you serialize an Object Linking and Embedding (OLE)
// container document for reasons other than File Open or Save, you must explicitly set
// m_pDocument. For example, you would do this when serializing a container document to
// the Clipboard
CFile myFile(m_csPathname, CFile::modeCreate | CFile::modeWrite);
CArchive ar(&myFile, CArchive::store);
//POSITION pos = ar.m_pDocument->GetFirstViewPosition(); // APPCRASH
//ar.m_pDocument->GetNextView(pos); // WHAT POSITION ?
CMainFrame * pMain = (CMainFrame*)AfxGetMainWnd();
CWinAESView * pView = (CWinAESView*)pMain->GetActiveView();
if(ar.m_pDocument == NULL) MessageBox(NULL, "It's NULL!", "Save As", MB_OK);
// Serialize the document to the archive.
if (ar.m_pDocument != NULL)
m_csTitle = m_csFilename;
Note that the above method saves an empty file to the directory and that the m_pDocument is invariably NULL.
I am certain that there is a way to accomplish my task. Can anyone please help?
Re: How to use CDocManager in CDocument OnSaveAs override ?
Perhaps you are having problems because RichEdit controls (and most other controls) violate the doc/view architecture: Unlike doc/view, RichEdits invariably store their contents inside the control itself, rather than inside some document that's separated from the view.
If this is the cause of your problem (a guess), then it might be helpful to look at the CRichEdit::StreamOut function. If you were doing this from the Main Frame (you're not), then code might look like this. Note that this is "found" code, and is not correct insofar as Unicode usage is concerned (please confirm that you are building a non-Unicode build, since your sample code is non-Unicode too). It should not be used as-is, but is merely being offered to prompt you with some ideas:
// szFilters is a text string that includes two file name filters:
// "*.txt" for "Text Files" and "*.*" for "All Files."
char szFilters= "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||";
// Create an Open dialog; the default file name extension is ".my".
CFileDialog fileDlg (FALSE, "txt", "*.txt",
OFN_OVERWRITEPROMPT| OFN_HIDEREADONLY, szFilters, this);
// Display the file dialog. When user clicks OK, fileDlg.DoModal()
// returns IDOK.
if( fileDlg.DoModal ()==IDOK )
m_strPathname = fileDlg.GetPathName();
CFile cFile(m_strPathname, CFile::modeCreate|CFile::modeWrite);
es.dwCookie = (DWORD) &cFile;
es.pfnCallback = (EDITSTREAMCALLBACK) MyStreamOutCallback;
m_RichEdit.StreamOut(SF_RTF,es); // Perform the streaming
/* The following function MyStreamOutCallback must be declared as
in the header file*/
DWORD CALLBACK MyStreamOutCallback(CFile* dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
// Required for StreamOut
CFile* pFile = (CFile*) dwCookie;
*pcb = cb;