MFC中保存过程详解

本文主要介绍,在MFC中菜单保存命令的响应过程。

一、MFC保存命令的响应过程:

File->Save对应的ID为ID_FILE_SAVE,其响应过程如下:

首先调用响应函数 CDocument::OnFileSave(),其函数原型如下:

void CDocument::OnFileSave() 
{ 
        DoFileSave(); 
}

由此可见,CDocument::OnFileSave()调用了 DoFileSave()函数,其函数原型如下:

BOOL CDocument::DoFileSave() 
{ 
	DWORD dwAttrib = GetFileAttributes(m_strPathName); 
	
	if (dwAttrib & FILE_ATTRIBUTE_READONLY) //如果文件是只读,或已经不存在了 
	{ 
		//使用DoSave(NULL) 
		if (!DoSave(NULL)) 
		{ 
			TRACE0("Warning: File save with new name failed.\n"); 
			return FALSE; 
		} 
	} 
	else 
	{ 
		//使用DoSave(....) 
		if (!DoSave(m_strPathName)) 
		{ 
			TRACE0("Warning: File save failed.\n"); 
			return FALSE; 
		} 
	} 
	return TRUE; 
}
此时如果操作的文件是只读或者已不存在,则不能实现对操作结果保存,否则调用DoSave()函数,其函数原型如下:

BOOL CDocument::DoSave(LPCTSTR lpszPathName, BOOL bReplace)  
{ 
	CString newName = lpszPathName; 
	if (newName.IsEmpty())  //如果文件名参数为空,则获取文档的路径名,加上扩展符
	{ 
		CDocTemplate* pTemplate = GetDocTemplate(); 
		ASSERT(pTemplate != NULL); 
		newName = m_strPathName; 
		if (bReplace && newName.IsEmpty()) 
		{ 
			newName = m_strTitle; 
			// check for dubious filename 
			int iBad = newName.FindOneOf(_T(" #%;/\\")); 
			if (iBad != -1) 
				newName.ReleaseBuffer(iBad); 
			// append the default suffix if there is one 
			CString strExt; 
			if (pTemplate->GetDocString(strExt, CDocTemplate::filterExt) && 
					!strExt.IsEmpty()) 
			{ 
				ASSERT(strExt[0] == '.'); 
				newName += strExt; 
			} 
		} 
		//bReplace为TRUE则显示保存文件对话框(AFX_IDS_ SAVEFILE),
		//否则显示拷贝保存对话框(AFX_IDS+SAVEFILECOPY)  
		if (!AfxGetApp()->DoPromptFileName(newName, 
					bReplace ? AFX_IDS_SAVEFILE : AFX_IDS_SAVEFILECOPY, 
							OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, FALSE, pTemplate)) 
			return FALSE;       // don't even attempt to save 
	} 
	CWaitCursor wait; 
	//保存,由OnSaveDocument完成 
	if (!OnSaveDocument(newName)) 
	{ 
		if (lpszPathName == NULL) 
		{ 
			// be sure to delete the file 
			TRY 
			{ 
				CFile::Remove(newName); 
			} 
			CATCH_ALL(e) 
			{ 
				TRACE0("Warning: failed to delete file \n"); 
				DELETE_EXCEPTION(e); 
			} 
			END_CATCH_ALL 
		} 
		return FALSE; 
	} 
	// reset the title and change the document name 
	if (bReplace) 
	SetPathName(newName); 
	return TRUE;        // success 
}
DoSave()函数先判段文件名参数是否为空,如果为空,则重新获取文件名,否则调用OnSaveDocument()函数,其函数原型如下:
BOOL CDocument::OnSaveDocument(LPCTSTR lpszPathName) 
{ 
	CFileException fe; 
	CFile* pFile = NULL; 
	pFile = GetFile(lpszPathName, CFile::modeCreate | 
	CFile::modeReadWrite | CFile::shareExclusive, &fe); 
	if (pFile == NULL) 
	{ 
		ReportSaveLoadException(lpszPathName, &fe, 
		   TRUE, AFX_IDP_INVALID_FILENAME); 
        return FALSE; 
	} 
	//建立保存用的CArchive 
	CArchive saveArchive(pFile, CArchive::store | CArchive::bNoFlushOnDelete); 
	saveArchive.m_pDocument = this; 
	saveArchive.m_bForceFlat = FALSE; 
	TRY 
	{ 
		CWaitCursor wait; 
		//使用文档类的序列化操作完成实际存档行为 
		Serialize(saveArchive);     // save me 
		saveArchive.Close(); 
		ReleaseFile(pFile, FALSE); 
	} 
	CATCH_ALL(e) 
	{ 
		ReleaseFile(pFile, TRUE); 
		TRY 
		{ 
		   ReportSaveLoadException(lpszPathName, e, 
			TRUE, AFX_IDP_FAILED_TO_SAVE_DOC); 
		} 
		END_TRY 
		DELETE_EXCEPTION(e); 
		return FALSE; 
	} 
	END_CATCH_ALL 
	SetModifiedFlag(FALSE);     // back to unmodified 
	return TRUE;        // success 
}

由此实现了对文件的保存过程,OnSaveDocument()函数也即是"工程名Doc.cpp"中的函数。

由此MFC中保存命令的响应过程已介绍完了,其响应过程为:

(1)首先调用 CDocument::OnFileSave()OnFileSave调用CDocument::DoFileSave()

(2)CDocument::DoFileSave()判断文件是否只读,是则DoSave(NULL),否则调用DoSave(m_strPathName)

(3)CDocument::DoSave(LPCTSTR lpszPathName,BOOL bReplace=TRUE)的流程为:     

       第一步:判断lpszPathName不空 ,则跳第二步,为空则获取文档的路径名,加上扩展符。bReplaceTRUE,则显示保存文件对话框框,否则

                     显示拷贝保存对话框

第二步:调用CDocument::OnSaveDocument()保存文档。

第三步:若bReplace==TRUESetPathName(newName)覆盖当前路径名。

(4)CDocument::OnSaveDocument()打开文件,创建CArchive对象saveArchive,Serialize(saveArchive)读写文件,SetModifiedFlag(FALSE)。


你可能感兴趣的:(mfc,mfc,save,ID_FILE_SAVE,MFC保存过程,保存响应过程)