MFC MDI 打开文件的调用过程

来源:互联网 发布:剑灵男灵族捏脸数据 编辑:程序博客网 时间:2024/06/08 05:31

1,

ON_COMMAND(ID_FILE_OPEN, CWinAppEx::OnFileOpen)


2,

void CWinApp::OnFileOpen()
{
ENSURE(m_pDocManager != NULL);
m_pDocManager->OnFileOpen();
}


3,

void CDocManager::OnFileOpen()
{
// prompt the user (with all document templates)

//显示打开对话框,获取打开文件的路径
CString newName;
if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,
 OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, NULL))
return; // open cancelled


AfxGetApp()->OpenDocumentFile(newName);
// if returns NULL, the user has already been alerted
}

3,

CDocument* CWinApp::OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToMRU)
{
ENSURE_VALID(m_pDocManager);
return m_pDocManager->OpenDocumentFile(lpszFileName, bAddToMRU);
}

4,

CDocument* CDocManager::OpenDocumentFile(LPCTSTR lpszFileName, BOOL bAddToMRU)
{
if (lpszFileName == NULL)
{
AfxThrowInvalidArgException();
}
// find the highest confidence
POSITION pos = m_templateList.GetHeadPosition();
CDocTemplate::Confidence bestMatch = CDocTemplate::noAttempt;
CDocTemplate* pBestTemplate = NULL;
CDocument* pOpenDocument = NULL;


TCHAR szPath[_MAX_PATH];
ASSERT(lstrlen(lpszFileName) < _countof(szPath));
TCHAR szTemp[_MAX_PATH];
if (lpszFileName[0] == '\"')
++lpszFileName;
Checked::tcsncpy_s(szTemp, _countof(szTemp), lpszFileName, _TRUNCATE);
LPTSTR lpszLast = _tcsrchr(szTemp, '\"');
if (lpszLast != NULL)
*lpszLast = 0;

if( AfxFullPath(szPath, szTemp) == FALSE )
{
ASSERT(FALSE);
return NULL; // We won't open the file. MFC requires paths with
            // length < _MAX_PATH
}


TCHAR szLinkName[_MAX_PATH];
if (AfxResolveShortcut(AfxGetMainWnd(), szPath, szLinkName, _MAX_PATH))
Checked::tcscpy_s(szPath, _countof(szPath), szLinkName);


while (pos != NULL)
{

//遍历m_templateList中保存的的Doctemplate,逐个和欲打开的文件名称进行匹配
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
ASSERT_KINDOF(CDocTemplate, pTemplate);


CDocTemplate::Confidence match;
ASSERT(pOpenDocument == NULL);
match = pTemplate->MatchDocType(szPath, pOpenDocument);

//匹配成功或者发现此文件已经打开,前者保存为pBestTemplate,且此时pOpenDocument为NULL
if (match > bestMatch)
{
bestMatch = match;
pBestTemplate = pTemplate;
}
if (match == CDocTemplate::yesAlreadyOpen)
break;      // stop here
}


if (pOpenDocument != NULL)
{
POSITION posOpenDoc = pOpenDocument->GetFirstViewPosition();
if (posOpenDoc != NULL)
{
CView* pView = pOpenDocument->GetNextView(posOpenDoc); // get first one
ASSERT_VALID(pView);
CFrameWnd* pFrame = pView->GetParentFrame();


if (pFrame == NULL)
TRACE(traceAppMsg, 0, "Error: Can not find a frame for document to activate.\n");
else
{
pFrame->ActivateFrame();


if (pFrame->GetParent() != NULL)
{
CFrameWnd* pAppFrame;
if (pFrame != (pAppFrame = (CFrameWnd*)AfxGetApp()->m_pMainWnd))
{
ASSERT_KINDOF(CFrameWnd, pAppFrame);
pAppFrame->ActivateFrame();
}
}
}
}
else
TRACE(traceAppMsg, 0, "Error: Can not find a view for document to activate.\n");


return pOpenDocument;
}


if (pBestTemplate == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_OPEN_DOC);
return NULL;
}

//用匹配的Doctemplate开启Doc,View,Frame组合
return pBestTemplate->OpenDocumentFile(szPath, bAddToMRU, TRUE);
}

CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bAddToMRU, BOOL bMakeVisible)
{

//创建CDocument对象
CDocument* pDocument = CreateNewDocument();
if (pDocument == NULL)
{
TRACE(traceAppMsg, 0, "CDocTemplate::CreateNewDocument returned NULL.\n");
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return NULL;
}
ASSERT_VALID(pDocument);


BOOL bAutoDelete = pDocument->m_bAutoDelete;
pDocument->m_bAutoDelete = FALSE;   // don't destroy if something goes wrong

//创建frame和View对象并创建相应的窗口
CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);
pDocument->m_bAutoDelete = bAutoDelete;
if (pFrame == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
delete pDocument;       // explicit delete on error
return NULL;
}
ASSERT_VALID(pFrame);


if (lpszPathName == NULL)
{
// create a new document - with default document name
SetDefaultTitle(pDocument);


// avoid creating temporary compound file when starting up invisible
if (!bMakeVisible)
pDocument->m_bEmbedded = TRUE;


if (!pDocument->OnNewDocument())
{
// user has be alerted to what failed in OnNewDocument
TRACE(traceAppMsg, 0, "CDocument::OnNewDocument returned FALSE.\n");
pFrame->DestroyWindow();
return NULL;
}


// it worked, now bump untitled count
m_nUntitledCount++;
}
else
{
// open an existing document
CWaitCursor wait;


if (!pDocument->OnOpenDocument(lpszPathName))//Serialize被调用,从文件中读取
{
// user has be alerted to what failed in OnOpenDocument
TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE.\n");
pFrame->DestroyWindow();
return NULL;
}
pDocument->SetPathName(lpszPathName, bAddToMRU);
pDocument->OnDocumentEvent(CDocument::onAfterOpenDocument);
}

设置frame的title
InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
return pDocument;
}


总体可看出在打开一个新文件时,App类,DocManager类,Doctemplate类 的各自职责

同时也将 View doc Frame和Docteplate进行了一些粘合


原创粉丝点击