MFC OnFileNew OnFileOpen过程分析代码.docx
《MFC OnFileNew OnFileOpen过程分析代码.docx》由会员分享,可在线阅读,更多相关《MFC OnFileNew OnFileOpen过程分析代码.docx(20页珍藏版)》请在冰豆网上搜索。
MFCOnFileNewOnFileOpen过程分析代码
MFCOnFileNewOnFileOpen过程分析代码
对OnFileNew()/OnFileOpen()的MFC代码跟踪简析,简析可能也谈不上了,为了快速的理解MFC的实现思路以及文档视图架构的应用,在学习的过程当中我也没有进行学习理解的注解。
不过细细阅读整个的实现流程,相信你我都能理解掌握MFC的整体思路。
以后有机会再进行注解吧。
A)OnFileNew()执行过程分析
1.voidCWinApp:
:
OnFileNew()
{
if(m_pDocManager!
=NULL)
m_pDocManager->OnFileNew();//只是调用CDocManager:
:
OnFileNew
}
注释:
MFC对ID_FILE_NEW菜单的响应函数,系统默认操作.
2.voidCDocManager:
:
OnFileNew()//文档模板管理器,维持了一个文档模板链表CPtrListm_templateList
{
if(m_templateList.IsEmpty())
{
TRACE0("Error:
nodocumenttemplatesregisteredwithCWinApp.\n");
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return;
}
CDocTemplate*pTemplate=(CDocTemplate*)m_templateList.GetHead();/*获得第一个文档模板,对于单文档只有一个文档模板*/
if(m_templateList.GetCount()>1)//对单文档这段没用
{
//morethanonedocumenttemplatetochoosefrom
//bringupdialogpromptinguser
CNewTypeDlgdlg(&m_templateList);
intnID=dlg.DoModal();
if(nID==IDOK)
pTemplate=dlg.m_pSelectedTemplate;
else
return;//none-canceloperation
}
ASSERT(pTemplate!
=NULL);
ASSERT_KINDOF(CDocTemplate,pTemplate);
pTemplate->OpenDocumentFile(NULL);/*其实是调用CMultiDocTemplate:
:
OpenDocumentFile函数下面祥述这里,因为在CDocTemplate类中这个函数是一个纯虚函数*/
//ifreturnsNULL,theuserhasalreadybeenalerted
}
注:
如果跳过此函数而手动操作直接进入pTemplate->OpenDocumentFile(),那么文档模版列表选择对话框也就不会出现了.
3.CDocument*CMultiDocTemplate:
:
OpenDocumentFile(LPCTSTRlpszPathName,BOOLbMakeVisible)
{
CDocument*pDocument=CreateNewDocument();//创建一个新文档
if(pDocument==NULL)
{
TRACE0("CDocTemplate:
:
CreateNewDocumentreturnedNULL.\n");
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
returnNULL;
}
ASSERT_VALID(pDocument);
BOOLbAutoDelete=pDocument->m_bAutoDelete;
pDocument->m_bAutoDelete=FALSE;//don'tdestroyifsomethinggoeswrong
CFrameWnd*pFrame=CreateNewFrame(pDocument,NULL);//根据新文档指针创建新文档框架
pDocument->m_bAutoDelete=bAutoDelete;
if(pFrame==NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
deletepDocument;//explicitdeleteonerror
returnNULL;
}
ASSERT_VALID(pFrame);
if(lpszPathName==NULL)
{
//createanewdocument-withdefaultdocumentname
SetDefaultTitle(pDocument);//设置缺省标题
//avoidcreatingtemporarycompoundfilewhenstartingupinvisible
if(!
bMakeVisible)
pDocument->m_bEmbedded=TRUE;
if(!
pDocument->OnNewDocument())//清除老文档内容
{
//userhasbealertedtowhatfailedinOnNewDocument
TRACE0("CDocument:
:
OnNewDocumentreturnedFALSE.\n");
pFrame->DestroyWindow();
returnNULL;
}
//itworked,nowbumpuntitledcount
m_nUntitledCount++;
}
else
{
//openanexistingdocument
CWaitCursorwait;
if(!
pDocument->OnOpenDocument(lpszPathName))
{
//userhasbealertedtowhatfailedinOnOpenDocument
TRACE0("CDocument:
:
OnOpenDocumentreturnedFALSE.\n");
pFrame->DestroyWindow();
returnNULL;
}
pDocument->SetPathName(lpszPathName);
}
InitialUpdateFrame(pFrame,pDocument,bMakeVisible);/*使框架中的视图窗口接受到OnInitialUpdat的调用,并作原始更新。
*/
returnpDocument;
}
4.CDocument*CDocTemplate:
:
CreateNewDocument()
{
//defaultimplementationconstructsonefromCRuntimeClass
if(m_pDocClass==NULL)//m_pDocClass文档类动态创建信息
{
TRACE0("Error:
youmustoverrideCDocTemplate:
:
CreateNewDocument.\n");
ASSERT(FALSE);
returnNULL;
}
//这是才真正的创建文档对象,这里创建的文档对象就是上面RUNTIME_CLASS(CFirstDoc)中的对象,这是MFC开发人员想出来的一种运行时创建对象的方法
CDocument*pDocument=(CDocument*)m_pDocClass->CreateObject();
if(pDocument==NULL)
{
TRACE1("Warning:
Dynamiccreateofdocumenttype%hsfailed.\n",
m_pDocClass->m_lpszClassName);
returnNULL;
}
ASSERT_KINDOF(CDocument,pDocument);
AddDocument(pDocument);//把创建的对象指针记录下来,以后还要用的
returnpDocument;
}
5.CFrameWnd*CDocTemplate:
:
CreateNewFrame(CDocument*pDoc,CFrameWnd*pOther)
{
if(pDoc!
=NULL)
ASSERT_VALID(pDoc);
//createaframewiredtothespecifieddocument
ASSERT(m_nIDResource!
=0);//musthavearesourceIDtoloadfrom
CCreateContextcontext;///创建CcreateContext对象.也就是我们重载LoadFrame函数的那个CcreateContext的来源*/
context.m_pCurrentFrame=pOther;///保存当前框架,一般为NULL
context.m_pCurrentDoc=pDoc;///保存文档对象指针
context.m_pNewViewClass=m_pViewClass;///保存视图对象指针
context.m_pNewDocTemplate=this;///保存文档模板的指针
if(m_pFrameClass==NULL)
{
TRACE0("Error:
youmustoverrideCDocTemplate:
:
CreateNewFrame.\n");
ASSERT(FALSE);
returnNULL;
}
CFrameWnd*pFrame=(CFrameWnd*)m_pFrameClass->CreateObject();///真正创建框架的对象
if(pFrame==NULL)
{
TRACE1("Warning:
Dynamiccreateofframe%hsfailed.\n",m_pFrameClass->m_lpszClassName);
returnNULL;
}
ASSERT_KINDOF(CFrameWnd,pFrame);
if(context.m_pNewViewClass==NULL)
TRACE0("Warning:
creatingframewithnodefaultview.\n");
//createnewfromresource
if(!
pFrame->LoadFrame(m_nIDResource,WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE,//defaultframestyles
NULL,&context))///加载资源
{
TRACE0("Warning:
CDocTemplatecouldn'tcreateaframe.\n");
//framewillbedeletedinPostNcDestroycleanup
returnNULL;
}
//itworked!
returnpFrame;
}
6.BOOLCDocument:
:
OnNewDocument()//清除老文档内容
{
if(IsModified())
TRACE0("Warning:
OnNewDocumentreplacesanunsaveddocument.\n");
DeleteContents();//删除原来的内容而不管是否存盘
m_strPathName.Empty();//nopathnameyet
SetModifiedFlag(FALSE);//makeclean//清除曾经修改过的标记
returnTRUE;
}
7.BOOLCDocument:
:
OnOpenDocument(LPCTSTRlpszPathName)
{
if(IsModified())
TRACE0("Warning:
OnOpenDocumentreplacesanunsaveddocument.\n");
CFileExceptionfe;
CFile*pFile=GetFile(lpszPathName,CFile:
:
modeRead|CFile:
:
shareDenyWrite,&fe);
if(pFile==NULL)
{
ReportSaveLoadException(lpszPathName,&fe,FALSE,AFX_IDP_FAILED_TO_OPEN_DOC);
returnFALSE;
}
DeleteContents();
SetModifiedFlag();//dirtyduringde-serialize
CArchiveloadArchive(pFile,CArchive:
:
load|CArchive:
:
bNoFlushOnDelete);
loadArchive.m_pDocument=this;
loadArchive.m_bForceFlat=FALSE;
TRY
{
CWaitCursorwait;
if(pFile->GetLength()!
=0)
Serialize(loadArchive);//loadme
loadArchive.Close();
ReleaseFile(pFile,FALSE);
}
CATCH_ALL(e)
{
ReleaseFile(pFile,TRUE);
DeleteContents();//removefailedcontents
TRY
{
ReportSaveLoadException(lpszPathName,e,
FALSE,AFX_IDP_FAILED_TO_OPEN_DOC);
}
END_TRY
DELETE_EXCEPTION(e);
returnFALSE;
}
END_CATCH_ALL
SetModifiedFlag(FALSE);//startoffwithunmodified
returnTRUE;
}
8.BOOLCFrameWnd:
:
LoadFrame(UINTnIDResource,DWORDdwDefaultStyle,CWnd*pParentWnd,CCreateContext*pContext)
{
//onlydothisonce
ASSERT_VALID_IDR(nIDResource);
ASSERT(m_nIDHelp==0||m_nIDHelp==nIDResource);
m_nIDHelp=nIDResource;//IDforhelpcontext(+HID_BASE_RESOURCE)
CStringstrFullString;
if(strFullString.LoadString(nIDResource))
AfxExtractSubString(m_strTitle,strFullString,0);//firstsub-string
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
//attempttocreatethewindow
LPCTSTRlpszClass=GetIconWndClass(dwDefaultStyle,nIDResource);///加载资源并注册窗口
LPCTSTRlpszTitle=m_strTitle;
if(!
Create(lpszClass,lpszTitle,dwDefaultStyle,rectDefault,pParentWnd,MAKEINTRESOURCE(nIDResource),0L,pContext))///创建框架窗口
{
returnFALSE;//willselfdestructonfailurenormally
}
//savethedefaultmenuhandle
ASSERT(m_hWnd!
=NULL);
m_hMenuDefault=:
:
GetMenu(m_hWnd);///获取并保存菜单句柄
//loadacceleratorresource
LoadAccelTable(MAKEINTRESOURCE(nIDResource));///装载加速键表
if(pContext==NULL)//sendinitialupdate
SendMessageToDescendants(WM_INITIALUPDATE,0,0,TRUE,TRUE);
returnTRUE;
}
9.voidDocTemplate:
:
InitialUpdateFrame(CFrameWnd*pFrame,CDocument*pDoc,BOOLbMakeVisible)
{
//justdelagatetoimplementationinCFrameWnd
pFrame->InitialUpdateFrame(pDoc,bMakeVisible);
}
10.voidCFrameWnd:
:
InitialUpdateFrame(CDocument*pDoc,BOOLbMakeVisible)
{
//iftheframedoesnothaveanactiveview,settofirstpane
CView*pView=NULL;
if(GetActiveView()==NULL)
{
CWnd*pWnd=GetDescendantWindow(AFX_IDW_PANE_FIRST,TRUE);
if(pWnd!
=NULL&&pWnd->IsKindOf(RUNTIME_CLASS(CView)))
{
pView=(CView*)pWnd;
SetActiveView(pView,FALSE);
}
}
if(bMakeVisible)
{
//sendinitialupdatetoallviews(andothercontrols)intheframe
SendMessageToDescendants(WM_INITIALUPDATE,0,0,TRUE,TRUE);
//giveviewachancetosavethefocus(CFormViewneedsthis)
if(pView!
=NULL)
pView->OnActivateFrame(WA_INACTIVE,this);
//finally,activatetheframe
//(sendthedefaultshowcommandunlessthemaindesktopwindow)
intnCmdShow=-1;//default
CWinApp*pApp=AfxGetApp();
if(pApp!
=NULL&&pApp->m_pMainWnd==this)
{
nCmdShow=pApp->m_nCmdShow;//usetheparameterfromWinMain
pApp->m_nCmdShow=-1;//settodefaultafterfirsttime
}
ActivateFrame(nCmdShow);
if(pView!
=NULL)
pView->OnActivateView(TRUE,pView,pView);
}
//updateframecountsandframetitle(mayalreadyhavebeenvisible)
if(pDoc!
=NULL)
pDoc->UpdateFrameCounts();
OnUpdateFrameTitle(TRUE);
}
B)OnFileOpen()执行过程分析
11.voidCWinApp:
:
OnFileOpen()
{
ASSERT(m_pDocManager!
=NULL);
m_pDocManager->OnFileOpen();
}
12.voidCDocManager:
:
OnFileOpen()
{
//prompttheuser(withalldocumenttemplates)
CStringnewName;
if(!
DoPromptFileName(newName,AFX_IDS_OPENFILE,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,TRUE,NULL))
return;//opencancelled
AfxGetApp()->OpenDocumentFile(newName);
//ifreturnsNULL,theuserhasalreadybeenalerted
}
13.CDocument*CWinApp:
:
OpenDocumentFile(LPCTSTRlpszFileName)
{
ASSERT(m_pDocManager!
=NULL);
returnm_pDocManager->OpenDocumentFile(lpszFileName);
}
14.CDocument*CDocManager:
:
OpenDocumentFile(LPCTSTRlpszFileName)
{
//findthehighestconfidence
POSITIONpos=m_templateList.GetHeadPosition();
CDocTemplate:
:
ConfidencebestMatch=CDocTemplate:
:
noAttempt;
CDocTemplate*pBe