文档类CDocument、子框架类CFrameWnd及视图类CView的关系及如何相互调用
文檔類、子框架類及視圖類的關系及如何相互調用 收藏
了解文檔和視圖的相互作用關系是編寫MFC程序的基本功。但是MFC的應用程序框架把文檔和視圖之間的關系封裝了起來,初學的朋友往往不得要領,因此寫程序往往被局限于在用向導生成的框架中。本文希望能夠盡可能說明白文檔視圖框架之間是如何進行作用,希望能給一些朋友帶來小小的幫助。??
? 幾個概念:??
? (雖然大家都知道了,雷神還是要重申一次)??
? 文檔對象:是用來保存數據的。??
? 視圖對象:是用來顯示和編輯數據的。??
? 應用程序框架:框架是用來管理不同文檔顯示界面的。例如你有一個數據網格顯示界面,還有一個圖形顯示界面,它們的數據可能都來自你的文檔,但是視圖不同,怎么辦用框架。為什么不用視圖?為的是把界面管理獨立的拿出來。??
? 文檔模板:MFC把文檔/視圖/框架視為一體,只要你創建文檔/視圖框架結構的程序,必定會為你創建這三個類。這個工作在在應用程序初始化時完成,如下:??
???
? BOOL?? CMyHtmlApp::InitInstance()??
? {??
? //。。。。。。??
? CSingleDocTemplate*?? pDocTemplate;??
? pDocTemplate?? =?? new?? CSingleDocTemplate(??
? IDR_MAINFRAME,??
? RUNTIME_CLASS(CMyHtmlDoc),??
? RUNTIME_CLASS(CMainFrame),?????????????? //?? main?? SDI?? frame?? window??
? RUNTIME_CLASS(CMyHtmlView));??
? AddDocTemplate(pDocTemplate);??
? //。。。。。。??
? }??
???
? 單文檔:就是一次只能打開一個文件,和你的文檔類型支持的多少無關。你完全可以做一個單文檔的支持所有圖象格式的程序,只不過它一次只能打開一個文檔罷了。??
? 多文檔:就是你可以打開多個文件,和文檔類型也無關。你也可以作一個可以同時打開多個文檔的程序,但它只支持一種文檔類型。??
???
? 何時需要文檔/視圖框架結構???
? 首先你可以不使用文檔視圖這種框架結構,即便是在MFC中。你可以在你需要的時候選擇使用這種方式。你可以完成一個只有視圖沒有文檔的程序,例如一個基于對話框的應用。??
? 哪什么時候需要呢???
? 當你想將你的數據層和界面層分開的時候。??
? 通常我們對數據的操作放在文檔類中,例如存取,打開,關閉。在這里你可以盡情的對你的數據進行操作,如果你需要,在對數據進行了改變后,對視圖做一下更新,那么程序會將你對數據所做的改變呈現給你的程序的用戶。由此可見視圖的作用就是提供一個用戶和數據之間進行數據交換的界面,它的作用就是在需要的時候顯示數據,并在需要的時候提供輸入界面。當用戶輸入后實際的數據操作工作是由文檔類來做的。那框架類有在做什么呢???
? 框架類是為了便于管理你的文檔類和視圖類而存在的。通常我們的操作都是通過視圖窗口完成,消息由視圖進行接收并且進行處理。所以消息映射定義一般在視圖中。但如果一個應用同時擁有多個視圖而當前活動視圖沒有對消息進行處理則消息會發往框架窗口。另外框架窗口可以方便的處理非窗口消息。??
???
? 再來說一邊典型的單文檔程序的生成過程(不完整,只挑有用的)??
? 1、?? CwinApp對象被建立,這個對象是全局的且只能有一個,名字叫theApp。這時你可以完成一些工作,例如對注冊表的操作,(如果你想寫一個不修改注冊表的軟件,需要在這里做寫工作)??
? 2、?? 在InitInstance()函數中創建文檔模板,文檔模板以CruntimClass靜態成員指針做構造參數。??
? 3、?? 執行MFC框架默認的命令行參數。命令行參數有很多其中之一是,Cmd1它會創建一個新文件。(如果沒有命令行參數則執行默認的ID_FILE_NEW)??
? 4、?? 文檔模板的實例根據三個類的動態創建信息創建出文檔、視圖、框架。??
? 5、?? 對文檔、視圖、框架進行初始化。??
???
? 我們對文檔,視圖,框架如何產生以及他們的用途有了一定的了解,如何有效的使用它們呢。??
???
? 文檔,視圖,框架之間的相互作用。??
? 由上面的典型的單文檔程序的生成過程可以看出一個完整的應用一般由四個類組成:CWinApp應用類,CFrameWnd框架類,CDocument文檔類,CView視圖類。我將四個類常用的成員函數列出,大家一看便知。不過參數,返回值均未列出,大家可以從MSDN上了解更多。幾個重要的虛函數也未做說明。大家自己看吧。??
???
? 通過全局函數AfxGetApp可以得到CWinApp應用類的全局對象theApp.??
? CwinApp??
? 數據成員:??
? m_pszAppName?? 應用程序名稱??
? m_pszExeName?? 可執行文件的名稱??
? m_pszProfileName?? INI文件的名??
? m_pszRegistryKey?? 注冊表或INI文件的KEY??
? m_hInstance?? 實例的句柄??
? m_pMainWnd?? 為框架窗口指針??
? 成員函數:??
? InitInstance()???? //初始化??
? ParseCommandLine()?? //完成命令行的解析處理??
???
? CFrameWnd??
? GetActiveDocument()?? //得到當前活動文檔指針??
? GetActiveView()?? //得到當前活動視圖指針??
? SetActiveView()?? //設置當前視圖為活動視圖??
???
? CDocument??
? OnNewDocument()??
? OnOpenDocument()??
? OnSaveDocument()??
? OnFileClose()??
? //以上是用來對文檔的操作??
? GetFirstViewPosition()?? //文檔對象鏈表中的第一個文檔位置??
? GetNextView()?? //下一個??
? //以上是用來遍歷所有和文檔關聯的視圖??
? GetDocTemplate()得到文檔模板指針??
? AddView()?? //增加一個視圖??
? RemoveView()?? //刪除一個視圖??
? UpdateAllView()?? //更新所有視圖??
???
? Cview??
? GetDocument()得到對應的文檔指針????
???
? 其他的就不列出了,大家還是看MSDN。你可以直接查看CWinApp應用類,CFrameWnd框架類,CDocument文檔類,CView視圖類的類成員。??
???
???
? 最后說說幾個常見到的問題。??
? 1,為什么在對話框的應用程序中沒有發現文檔模板???
? 默認的對話框程序沒有使用文檔/視圖框架結構。??
???
? 2 ,如果我使用數據庫作為數據源是否意味著可以不需要文檔類???
? 看你自己,但是我建議使用。因為可以文檔,視圖這一個清晰方便的框架結構,以及方便完成三者之間的相互作用。??
------------------------------------------------------------------------------------------------------------
框架、文檔、視圖類之間的調用關系
1、主框架(CFrameWnd)中訪問視圖(CView)
? CView* GetActiveView() const;
? 通常定義的視圖為CView的派生類,在調用自定義視圖對象的方法時
應該這樣寫:((CMouseKeyView*)GetActiveView())->MyFunc();
2、主框架(CFrameWnd)中訪問文檔(CDocument)
? GetActiveDocument,返回CDocument對象;
3、在視圖(CView)中訪問文檔(CDocument)
? inline CMouseKeyDoc* CMouseKeyView::GetDocument()
??? {return (CMouseKeyDoc*)m_pDocument;}
4、在視圖(CView)中訪問框架(CFrameWnd)
? CFrameWnd* GetParentFrame() const;
5、在文檔(CDocument)中訪問框架(CFrameWnd)
? CWnd* AfxGetMainWnd();
? CWnd* AfxGetApp()->m_pMainWnd;
6、在文檔(CDocument)中訪問視圖(CView)
? UpdateAllViews
? 功能:通知所有的視圖文檔已被修改的信息
? 原型:
??? void UpdateAllViews(
????? CView* pSender,? // 要更新的視圖指針,如果希望更新所有視
圖,將此參數設為NULL
????? LPARAM lHint=0L, // 包含更改消息的通知
????? CObject* pHint=NULL // 保管更改消息的對象
??? }
7、在其他類中訪問文檔類(CDocument)
? CDocument* GetDocument()
? {
??? CFrameWnd* frm=(CFrameWnd*)::AfxGetMainWnd();
??? ASSERT(frm);
??? CDocument* pDoc=frm->GetActiveDocument();
??? ASSERT(pDoc);
??? ASSERT(pDoc->IsKindOf(RUNTIME_CLASS(CMouseKeyDoc)));
??? return (CMouseKeyDoc*)pDoc;
? }
[注:資料轉載自網上]
?
?
————————————————————————————————————————————————————————————
?
? MFC中文檔和視圖的關系 收藏
1、應用程序對象有一個文檔模板管理器CDocManager* m_pDocManager(第一次調用AddDocTemplate時new出來)
2、文檔模板管理器有一個文檔模板對象列表CPtrList m_templateList(AddDocTemplate 函數負責添加該列表)
3、文檔模板對象擁有文檔、視圖、框架的靜態CRuntimeClass成員指針用于動態創建,還有一個m_nIDResource用來表示應采用的UI對象
4、每個文檔模板對象擁有 m_pOnlyDoc 或 m_docList (文檔指針或文檔指針列表),OnFileNew 和 OnFileOpen都調用文檔模板對象的OpenDocumentFile,OpenDocumentFile 調用文檔模板的 CreateNewDocument,CreateNewDocument再調用文檔模板的 AddDocument 填充該文檔列表或文檔指針
5、文檔對象有一個文檔模板指針 m_pDocTemplate (回指文檔對象所屬模板對象).同上,也是文檔模板的 AddDocument 成員函數把 this 指針(文檔模板自身).塞給剛剛創建的文檔對象
6、文檔對象有一個 m_viewList(視圖列表),OnFileNew 和 OnFileOpen 都調用文檔模板對象的OpenDocumentFile,該函數調用 CreateNewDocument 創建文檔,然后調用 CreateNewFrame 創建框架對象.
?? CreateNewFrame 構造CCreateContext對象
?? CCreateContext兩個重要字段:(1)剛創建的文檔指針(2)視圖的CRuntimeClass指針
?? CreateNewFrame 創建框架對象后由該對象調用 LoadFrame
?? LoadFrame 的最后一個參數即為 CCreateContext 指針
?? LoadFrame 調用 Create,Create 再調用 CreateEx 最后一個參數均為此CCreateContext指針
?? Create的調用由消息映射表引發CFrameWnd::OnCreate被調用
?? OnCreate的LPCREATESTRUCT的一個字段lpCreateParams 仍然是這個CCreateContext指針
?? 則在CFrame::OnCreate中,由這個CCreateContext的CRuntimeClass(視圖的)來調用CreateObject
?? 產生視圖對象后,由該對象調用Create(最后一個參數仍然是這個CCreateContext指針)
?? 視圖對象的Create由消息映射表引發視圖對象的OnCreate被調用
?? 視圖的OnCreate的參數 LPCREATESTRUCT 的 lpCreateParams 還是這個CCreateContext指針)
?? 于是利用 CCreateContext 的成員 m_pCurrentDoc (當前文檔)
?? 來調用 CDocument::AddView 把視圖加入文檔的視圖列表
7、視圖有一個文檔指針m_pDocument (指向所屬文檔)
?? 同上,也是CDocument::AddView函數初始化的,如下所示:
?? pView->m_pDocument = this;
8、框架有一個m_pViewActive(活動視圖)
?? 由框架的SetActiveView進行設置
轉載于:https://www.cnblogs.com/cwbo-win/p/3371707.html
總結
以上是生活随笔為你收集整理的文档类CDocument、子框架类CFrameWnd及视图类CView的关系及如何相互调用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 也谈软件的开发成本
- 下一篇: linux的 su 错误 Permiss