mfc文檔視圖結構


文檔視圖結構中操作流程

一基本架構

一個程序可以看作是建立在對文檔進行處理的基礎上的,而程序可處理的文檔類型有可能有多種,同時每種文檔又可能同時被打開多個視圖,若在MDI程序中存在多個文檔模板,這會在啟動程序時顯示一個新建對話框,其中每個條目顯示一個文檔模板字符串中第三個子串。每個文檔又可分為數據部分和表現部分。

基於這種認識,MFC文檔視圖框架結構將各功能模塊總結為對象,用相互關聯的這些對象類來建立應用程序.

①文檔類型管理

CWinApp代表程序,它可處理多種類型的文檔,這樣,就必須有一個存儲管理文檔類型的內部成員,這個成員就是

CDocManager * m_pDocManager

CDocManager負責管理文檔類型

CDocManager內部用

CPtrList m_templateList;(指針鏈表)

記錄文檔類型

②文檔類型實現

CDocTemplate(文檔模板)代表具體的文檔類型

一個程序所能處理的文檔類型,對對應各自的文檔模板

這些模板對象的指針被記錄在m_templateList,並且由m_pDocManager管理

③文檔模板的實現

對於某一種文檔,其內部數據結構,及外部表現形式,及針對它的操作命令都相對固定,因此文檔模板有三個構成部分,文檔的數據,用CDoucument管理;文檔的表現形式,CView表示;文檔在窗口系統中的容器,及菜單,工具條等命令形式則由CFrameWnd管理。必要時,同一文檔可能需要多種表達,即一個CDocument可能關聯幾個CView,但模板聲明時,只考慮一個文檔對應一個視圖,即作為默認時的活動視圖,可是重載CFramwWnd::OnCreateClient設置其他的視圖,例如靜態分割窗口。

這些信息被記錄在其三個成員中

CRuntimeClass* m_pDocClass; // class for creating new documents

CRuntimeClass* m_pFrameClass; // class for creating new frames

CRuntimeClass* m_pViewClass; // class for creating new views

一各文檔模板,對應一種文件類型,而這一類型的文件則可以有很多,這些對應的文件將記錄在

CPtrList m_docList;

另外,文檔模板也包含了該文檔類型所對應的資源,如菜單,標題,圖標等等信息

二 文檔類型的建立

程序執行之初,(InitInstance 中)將建立文檔類型鏈表

依次建立多個文檔類型(CCMultiDocTemplate),再一一添加(AddDocTemplate)到CWinApp的文檔類型列表m_templateList中這樣就建立了一個文件類型表,文件的新建,打開都將首先查找這個文件類型鏈表,找出文檔的類型,得到文檔模板,由文檔模板得到文檔應有的數據結構、文檔的圖形表述,及操作等等。

三 文檔的新建

①界面 命令ID_FILE_NEW發出

CWinApp::OnFileNew()處理

交由CDocManager * m_pDocManager(文檔類型管理)處理

②CDocuManager查看文件類型列表,如過程序支持多種類型文檔,給出一個類型選擇機會。

若文檔類型列表中只有一種文檔類型,直接選用這種類型。

③找到文檔模板后,將調用文檔模板的OpenDocumentFile(..)成員,傳入的參數為NULL,表示新建

i . OpenDocumentFile首先將首先建立文檔的數據部分:

CDocument* pDocument = CreateNewDocument();

這將按照m_pDocClass所記錄的CDocument類建立其實際數據對象。

數據對象建立后,將其添加到CPtrList m_docList中,記錄下這一文檔模板對應打開的所有實際文件。 同時,CDocument也有一個列表CPtrList m_viewList; 用於記錄文檔對象所對應的(CView)視圖,視圖 容許有多個(同樣的數據,可能有需要不同的表達形式)。

ii. 為數據建立其表現形式的容器,即框架窗口

CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);

根據文檔模板記錄的框架類m_pFrameClass建立框架對象。

iii. 建立框架對象的同時,CView(數據的表現形式,數據圖像)的類型m_pViewClass將作為參數傳給框架對象

CCreateContext context;

context.m_pNewViewClass = m_pViewClass;

然后框架對象建立其實際的窗口 if (!pFrame->LoadFrame(m_nIDResource, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, // default frame stylesNULL, &context))

LoadFrame 中將調用Create生成窗口,

框架窗口建立客戶區時,將調用CreateView(pContext, AFX_IDW_PANE_FIRST)建立模板所制定的CView對象

並建立窗體pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0), this, nID, pContext))

在CView建立時,其OnCreate()中將自己添加到對應文檔的視圖列表中:

pContext->m_pCurrentDoc->AddView(this);

④文檔對象(一般將文檔(文件)的數據部分成為文檔對象,與前面提到的文檔意義有區別),文檔對象的表現部分(視圖對象) 及視圖對象在Windows系統中的窗口容器(框架對象)自此都建立好了,接下來,是各對象的初始化。

i. pDocument->OnNewDocument()

在OnNewDocument()中有用戶實現相應數據的新建或初始。

完成后,將m_nUntitledCount增1,這個數用來對新文檔進行計數,好用來給新文件起缺省名(例如:未命名3.txt);

(如果OpenDocumentFile(.)有參數(打開文件時),在這兒將調用的是pDocument->OnOpenDocument() 用文件中的數據初始數據對象,)

ii. InitialUpdateFrame初始化框架

InitialUpdateFrame中將激活一個CView對象(若無,則為其他子窗口)

並且向所有子窗口發送SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);

WM_INITIALUPDATE是MFC自定義的消息,用於在此時實現相關初始化,

在CView::OnInitialUpdate中可寫入需要添加的初始操作。

激活框架窗口或相應視圖。

其后,更新框架窗口標題

⑤自此,新建文檔過程結束。

在msdn中有幾個比較直觀的圖,這里copy過來

文檔的創建順序

框架窗口的創建順序

視圖的創建順序

四 文檔的打開

①響應打開命令 ID_FILE_OPEN

CWinApp::OnFileOpen()

調用m_pDocManager->OnFileOpen();

②DoPromptFileName提供打開文件對話框,得到文件名

③調用AfxGetApp()->OpenDocumentFile(newName);

(這與新建文件有所不同)

這是應用程序類的一個虛函數,可以添加特定處理於此

一般情況下,將接着調用CWinApp::OpenDocumentFile(newName);

④回到CDocManager

m_pDocManager->OpenDocumentFile(lpszFileName);

查找文檔模板列表,找出文檔應該采用的文檔模板。

調用各模板的MatchDocType 判斷是否合適,或是否已經打開過了。

pTemplate->MatchDocType(szPath, pOpenDocument)

若文件已經被某模板打開過,激活相應框架,試圖。

若沒打開,單有相符合模板,使用該文檔模板打開文件

pBestTemplate->OpenDocumentFile(szPath);

若不是程序處理的文件類型,報錯返回。

⑤用找到的最合適文檔模板打開文件。

CMultiDocTemplate::OpenDocumentFile

⑥ ....

以下各步驟與新建文件③以后各步相同,只是傳入參數不同

建立文檔對象后,初始化時,將調用CDocumet::OpenDocumentFile 而不是CDocumet::OnNewDocument();

昨天晚上正好遇到一個問題,就是點擊“打開”菜單彈出的打開對話框的文件類型過濾本來是在IDR_MAINFRAME的第四、五段,但是貌似只能添加一個文本過濾類型,於是我在文檔窗口中接受ID_FILE_OPEN消息,在消息響應函數中自己做一個CFileDialog來彈出打開對話框,在其中可以自由滴處理過濾類型,然后調用AfxGetApp()->OpenDocumentFile(dlg.GetPathName())、、、

順便說下,在MDI中命令消息處理流程是:CView->CDocument->CChildFrame->CMainFrame->CWinApp,其他的不是派生於CWnd的對象就不會響應窗口消息。

轉自http://blog.chinaunix.net/uid-24323834-id-2213979.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM