In the MFC multi-document program, closing a document from the menu has different effects than directly clicking the x in the upper right corner.
If the document content is modified, the former will ask the user whether to save the modifications; the latter will close directly without saving the modifications.
The reason is that when closing from the menu, calling OnClose will definitely call SaveModified(), the source code is as follows
/
// Standard file menu commands
void CDocument::OnFileClose()
{
if (!SaveModified())
return;
// shut it down
OnCloseDocument();
// this should destroy the document
}
When clicking x to close, the CanCloseFrame() function will determine whether to save the document. The source code is as follows:
BOOL CDocument::CanCloseFrame(CFrameWnd* pFrameArg)
// permission to close all views using this frame
// (at least one of our views must be in this frame)
{
ASSERT_VALID(pFrameArg);
UNUSED(pFrameArg); // unused in release builds
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
ASSERT_VALID(pView);
CFrameWnd* pFrame = pView->GetParentFrame();
// assume frameless views are ok to close
if (pFrame != NULL)
{
// assumes 1 document per frame
ASSERT_VALID(pFrame);
if (pFrame->m_nWindow > 0)
return TRUE; // more than one frame refering to us
}
}
// otherwise only one frame that we know about
return SaveModified();
}
SaveModified()
It can be seen that the statement will only be executed when the window of the parent frame is 0 , and TRUE will only be returned in other cases. When using multi-document programming, be careful to add SaveModified()
statements to your own overloaded CanCloseFrame() for the sake of document security.
How to save silently without asking the user?
CDocument::SaveModified()
The implementation is as follows:
BOOL CDocument::SaveModified()
{
if (!IsModified())
return TRUE; // ok to continue
// get name/title of document
CString name;
if (m_strPathName.IsEmpty())
{
// get name based on caption
name = m_strTitle;
if (name.IsEmpty())
VERIFY(name.LoadString(AFX_IDS_UNTITLED));
}
else
{
// get name based on file title of path name
name = m_strPathName;
if (afxData.bMarked4)
{
AfxGetFileTitle(m_strPathName, name.GetBuffer(_MAX_PATH), _MAX_PATH);
name.ReleaseBuffer();
}
}
CString prompt;
AfxFormatString1(prompt, AFX_IDP_ASK_TO_SAVE, name);
switch (AfxMessageBox(prompt, MB_YESNOCANCEL, AFX_IDP_ASK_TO_SAVE))
{
case IDCANCEL:
return FALSE; // don't continue
case IDYES:
// If so, either Save or Update, as appropriate
if (!DoFileSave())
return FALSE; // don't continue
break;
case IDNO:
// If not saving changes, revert the document
break;
default:
ASSERT(FALSE);
break;
}
return TRUE; // keep going
}
It can be seen that the "save" action is actually performed DoFileSave()
, so developers can consider executing this function when the user performs certain actions and silently save the current editing results without popping up a dialog box for user confirmation.