VC選單命令詳解(檔案開啟、儲存與關閉)
第一部分:
五個命令ID: 處理函式
ID_FILE_NEW CWinApp::OnFileNew
ID_FILE_OPEN CWinApp::OnFileOpen
ID_FILE_SAVE CDocument::OnFileSave
ID_FILE_SAVEAS CDocument::OnFileSaveAs
ID_FILE_CLOSE CDocument::OnFileClose
1.ID_FILE_NEW
CWinApp::OnFileNew呼叫CDocManager::OnFileNew。
|
CDocManager::OnFileNew判斷文件模板是否多於一個,是則顯示文件型別對話方塊(AFX_IDD_NEWTYPEDLG)
讓使用者選擇要建立的文件型別。然後呼叫CDocTemplate::OpenDocumentFile(NULL)。
|
CDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,BOOL bMake_Visible=TRUE)對於SDI和MDI的
處理不一樣。
對於SDI,1,若已有文件開啟,對其重新初始化,呼叫CDocument::SaveModified()儲存當前文件;若沒
有文件存在,則呼叫CreateNewDocument()建立文件物件,再呼叫CreateNewFrame(pDoucment,NULL)建立
文件的框架視窗。2,若lpszPathName為NULL,則呼叫CDocument::OnNewDocument()處理新文件,用
pDocument->SetPathName(lpszPathName)設定文件的路徑。3,判斷當前執行緒主框架視窗是否存在,不存
在則將1中建立的新框架作為主框架。4,呼叫InitialUpdateFrame顯示框架視窗。
對於MDI,與SDI基本相同,但是沒有第3步。
|
CDocument::OnNewDocument()首先呼叫DeleteContents()刪除原文件內容,使用m_strPathName.Empty()
清除當前文件路徑,SetModifiedFlag(FALSE)。
2.ID_FILE_OPEN
|
CDocManager::OnFileOpen首先顯示檔案開啟對話方塊(AFX_IDS_OPENFILE),然後呼叫CWinApp::
OpenDocumentFile(FileName)。
|
CWinApp::OpenDocumentFile(FileName)呼叫CDocManager::OpenDocumentFile。
|
CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)遍歷文件模板,對每個模板用
MatchDocType(szPath,pOpenDocument)匹配文件型別。匹配時主要根據副檔名判斷。若檔案已經在
某個文件中開啟,則啟用文件的第一個檢視,否則用匹配的文件模板pBestTemplate->OpenDocumentFile
(szPath)。
|
CDocTemplate::OpenDocumentFile呼叫CDocument::OnOpenDocument開啟檔案。
|
CDocument::OnOpenDocument開啟檔案,用DeleteContents刪除現有文件內容,建立檔案對應的CArchive
物件loadArchive,Serialize(loadArchive)讀檔案內容,SetModifiedFlage(FALSE)。
MDI: New Frame, New View?
SDI: Update View?
3.ID_FILE_SAVE
CDocument::OnFileSave呼叫CDocument::DoFileSave()。
|
CDocument::OnFileSave判斷檔案是否只讀,是則DoSave(NULL),否則DoSave(m_strPathName)。
|
CDocument::DoSave(LPCTSTR lpszPathName,BOOL bReplace=TRUE)的流程為:1,判斷lpszPathName不空
則跳第二步,為空則獲取文件的路徑名,加上擴充套件符。bReplace為TRUE則顯示儲存檔案對話方塊(AFX_IDS_
SAVEFILE),否則顯示拷貝儲存對話方塊(AFX_IDS+SAVEFILECOPY)。2,呼叫CDocument::OnSaveDocument保
存文件。3,若bReplace==TRUE則SetPathName(newName)覆蓋當前路徑名。
|
CDocument::OnSaveDocument開啟檔案,建立CArchive物件saveArchive,Serialize(saveArchive)讀寫
檔案,SetModifiedFlag(FALSE)。
4.ID_FILE_SAVEAS
CDocument::OnFileSave呼叫DoSave(NULL)。
5.ID_FILE_CLOSE
CDocument::OnFileClose呼叫SaveModified()儲存檔案,再用OnCloseDocument處理文件關閉。
|
CDocument::SaveModified()用IsModified()判斷是否修改,是則顯示檔案儲存對話方塊(AFX_IDP_ASK_TO_
SAVE),若使用者選擇“是”,則呼叫DoFileSave()儲存檔案。
|
CDocument::OnCloseDocument()首先銷燬文件框架,再用DeleteContents()刪除文件內容,若m_
bAutoDelete則delete this。
第二部分:
MDI開啟檔案的過程
CWinApp::OnFileOpen()
{
CDocManager::OnFileOpen()
{
CDocManager::DoPromptFileName()
{
CFileDialog::DoModal();
}
CWinApp::OpenDocumentFile()
{
...選擇文件模板;
...調整檢視和框架;
CDocTemplate::OpenDocumentFile();
{
判斷有無現存文件,是否需要儲存
新建框架
判斷檔案是否存在,呼叫CMyDoc::OnOpenDocunment/OnNewDocument
}
}
}
}
----------------------------------------
Document/View命令處理流程
ID_FILE_NEW
CWinApp::OnFileNew()
{
CDocManager::OnFileNew()
{
if(沒有文件模板)
return;
if(有多個文件模板)
{
彈出對話方塊讓使用者選擇;
取得模板指標;
}
CMultiDocTemplate::OpenDocumentFile()
{
new一個文件;
建立子框架;
構建frame,doc,view之間的關係;
CDocument::OnNewDocument()
{
DeleteContents();
}
InitialUpdateFrame();
return pDoc;
}
}
}
ID_FILE_OPEN
CWinApp::OnFileOpen()
{
CDocManager::OnFileOpen()
{
CDocManager::DoPromptFileName()
{
CFileDialog::DoModal();
}
CWinApp::OpenDocumentFile()
{
...選擇文件模板;
...調整檢視和框架;
CDocTemplate::OpenDocumentFile();
{
判斷有無現存文件,是否需要儲存
新建框架
判斷檔案是否存在
CMyDoc::OnOpenDocunment()
{
開啟檔案;
DeleteContents();
建立CArchive;
Serialize;
關閉CArchive;
}
}
}
}
}
ID_FILE_SAVE
CDocument::OnFileSave()
{
DoFileSave(NULL)
{
CFileDialog::DoModal();
OnSaveDocument()
{
CArchive;
Serialize;
}
}
}
***************************************************************
在這裡將講述SDI程式中application object、the main frame window、the document、the view、the document template object以及the associate string and menu resources之間的關係。
The Windows Application Object
在CWinApp派生類的Implement檔案中會有類似CMyApp theApp的語句。theApp是一個全域性變數,它就是啟動MFC應用程式的機制所在。
以下是MFC應用程式啟動的摘要:
1、Windows把應用程式載入到記憶體;
2、構造全域性變數theApp(所有全域性變數在程式被載入記憶體時被構造);
3、Windows呼叫全域性函式WinMain,它是MFC的一部分,等同於無視窗應用程式的main函式---主程式的入口;
4、WinMain尋找到CWinApp派生類的物件theApp;
5、WinMain為theApp呼叫InitInstance函式,InitInstance函式可以被過載;
6、過載的InitInstance函式啟動載入document、顯示the main frame and view windows;
7、WinMain為theApp啟動Run函式,Run函式負責分派window messages和command messages。
The Document Template Class
在CWinApp派生類的InitInstance中會有如下程式碼:
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CStudentDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CStudentView));
AddDocTemplate(pDocTemplate);
這段程式碼建立了the application class、the document class、the view window class、the main frame window四個類之間的聯絡。這時,application class的物件已經存在(theApp),但其他四個類的物件還沒有構造,MFC的動態建立機制就起到了作用。
一下兩個圖分別表示了以上四個類之間的關係、四個類的物件之間的關係:
Creating an Empty Document—The CWinApp::OnFileNew Function
當application class的InitInstance呼叫完AddDocTemplate以後,它將呼叫OnFileNew。
OnFileNew做如下事情:
1、構造Document物件,但不從硬碟中讀取資料;
2、構造the main frame物件和the main frame window,但不顯示它,它包括IDR_MAINFRAME、the toolbar、the status bar;
3、構造view物件和view視窗,但不顯示它;
4、建立the document、main frame、view物件之間的關係,這裡要藉助AddDocTemplate建立的類關係;
5、為document物件呼叫虛擬函式CDocument::OnNewDocument,CDocument::OnNewDocument函式將呼叫虛擬函式DeleteContent函式;
6、為view物件呼叫虛擬函式CView::OnInitialUpdate;
7、為frame物件呼叫CFrameWnd::ActivateFrame以顯示the main frame window(有the menus,view window,control bars)。
The Document Class's OnNewDocument Function
建構函式所完成的工作越少越好,這樣構造函數出錯的機率就會越來越小。而CDocument::OnNewDocument 和 CView::OnInitialUpdate 是做初始化的好地方。在這裡你可以彈出一個MessageBox。如果出錯,OnNewDocument還可以返回FALSE。值得注意的是,OnNewDocument可以被呼叫很多次,所以有些指令需只執行一次的話,就需要做一個“first time” flag成員變數。
Connecting File Open to Your Serialization Code—The OnFileOpen Function
檔案開啟選單對映到CWinApp::OnFileOpen函式,它將執行以下幾個步驟:
1、提示使用者選擇一個檔案;
2、呼叫虛擬函式CDocument::OnOpenDocument,CDocument::OnOpenDocument開啟檔案,呼叫CDocument::DeleteContents,並且構造一個CArchive物件。隨後呼叫document的Serialize函式從archive中載入資料;
3、呼叫view的OnInitialUpdate函式。
Connecting File Save and File Save As to Your Serialization Code
檔案儲存和另存為選單對映到CDocument的OnFileSave函式,OnFileSave函式依次呼叫Serialize函式,它使用一個archive物件進行儲存。
The Document's "Dirty" Flag
CDocument有一個protected成員函式m_bModified。可以通過CDocument的函式SetModifiedFlag和IsModified訪問m_bModified。當新建一個document或者讀取完硬碟上的資料後,m_bModified被Application Framework設為FALSE。當document的內容被改寫後要確保把m_bModified設為TRUE。
小結:OnFileNew和OnFileOpen都在Application類中,Application類裡面有DocumentTemplate,可以同時調動Document和View(OnInitialUpdate)。
OnFileSave和OnFileSaveAs都在Document類中,它只需做Serialization,不牽扯View的操作,故不需要把它們放在Application類中。