第7章單文檔和多文檔_第1頁
第7章單文檔和多文檔_第2頁
第7章單文檔和多文檔_第3頁
第7章單文檔和多文檔_第4頁
第7章單文檔和多文檔_第5頁
已閱讀5頁,還剩109頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第7章 單文檔和多文檔文檔是一個(gè)應(yīng)用程序數(shù)據(jù)基本元素的集合,它構(gòu)成應(yīng)用程序所使用的數(shù)據(jù)單元。另外它還提供了管理和維護(hù)數(shù)據(jù)的手段。文檔/視圖結(jié)構(gòu)的基本概念就是把對(duì)數(shù)據(jù)的管理與數(shù)據(jù)的顯示分開。學(xué)習(xí)本章,讀者可以掌握文檔/視圖結(jié)構(gòu)的基本原理,掌握基于單文檔和多文檔的應(yīng)用程序的開發(fā)。7.1 什么是文檔文檔/視圖是一種Windows常用的應(yīng)用程序形式,它將數(shù)據(jù)管理和顯示分離。Visual C+的MFC應(yīng)用程序框架支持3種不同的應(yīng)用程序,即單文檔界面、多文檔界面和對(duì)話框應(yīng)用程序。本節(jié)介紹文檔應(yīng)用程序的基本概念。7.1.1 單文檔界面VS多文檔界面單文檔應(yīng)用程序是指應(yīng)用程序只可以打開一個(gè)文檔,如常見的記事本

2、就是單文檔的典型應(yīng)用。多文檔應(yīng)用程序是指可以同時(shí)打開多個(gè)文檔,如Windows中的Word就是多文檔的典型應(yīng)用。在Visual C+中可以使用應(yīng)用程序向?qū)?chuàng)建基于單文檔或者多文檔的應(yīng)用程序。在Visual C+中開發(fā)單文檔和多文檔應(yīng)用程序時(shí),向?qū)щ[藏了兩者之間的很多差異。因此在開發(fā)兩種應(yīng)用程序時(shí)有很多的理念和方法是相似的。7.1.2 文檔/視圖結(jié)構(gòu)利用Visual C+的應(yīng)用程序向?qū)Э梢苑奖愕貏?chuàng)建文檔程序。當(dāng)利用向?qū)梢粋€(gè)應(yīng)用程序時(shí),它所創(chuàng)建的各個(gè)類緊密地聯(lián)系在一起。其中,數(shù)據(jù)的管理和數(shù)據(jù)的顯示分別由不同的類實(shí)現(xiàn),這樣整個(gè)程序就構(gòu)成一個(gè)文檔/視圖結(jié)構(gòu)。Windows應(yīng)用程序是基于事件驅(qū)動(dòng),或

3、者說是消息驅(qū)動(dòng)的。因此整個(gè)應(yīng)用程序還有一個(gè)框架類,即負(fù)責(zé)應(yīng)用程序與操作系統(tǒng)之間的消息傳遞,同時(shí)協(xié)調(diào)文檔/視圖之間的工作。文檔負(fù)責(zé)數(shù)據(jù)的管理,數(shù)據(jù)通常被保存在文檔類的數(shù)據(jù)成員中,而視圖類則負(fù)責(zé)數(shù)據(jù)的顯示。視圖可以在文檔類中讀取數(shù)據(jù),并負(fù)責(zé)將數(shù)據(jù)在屏幕中顯示出來。7.2 文檔/視圖應(yīng)用程序利用Visual C+應(yīng)用程序向?qū)Э梢苑奖愕貏?chuàng)建基于文檔/視圖結(jié)構(gòu)的應(yīng)用程序。它提供了整個(gè)應(yīng)用程序的框架,程序員只需要添加實(shí)現(xiàn)預(yù)定功能的代碼即可以完成功能強(qiáng)大的應(yīng)用程序。由于單文檔和多文檔的應(yīng)用開發(fā)基本相同,所以本節(jié)以單文檔為例介紹文檔/視圖應(yīng)用程序。7.2.1 構(gòu)建單文檔應(yīng)用程序創(chuàng)建單文檔應(yīng)用程序需要使用應(yīng)用程

4、序向?qū)Чδ?。使用該功能,可以方便的?chuàng)建應(yīng)用程序的框架。程序員可以在此基礎(chǔ)上添加實(shí)現(xiàn)預(yù)定功能的代碼,從而創(chuàng)建實(shí)現(xiàn)預(yù)定功能的應(yīng)用程序。【示例7.1】 通過應(yīng)用程序向?qū)?,建立單文檔應(yīng)用程序。操作過程如下所示。(1)啟動(dòng)Visual C+ 6.0,選擇File|New命令,彈出New對(duì)話框,如圖7.1所示。圖7.1 New對(duì)話框 (2)選擇Projects標(biāo)簽,然后在列表中選擇MFC AppWizardexe選項(xiàng)。在“Project name:”文本框中輸入工程文件名test。在“Location:”文本框中指定應(yīng)用程序創(chuàng)建的位置。單擊OK按鈕,彈出MFC AppWizard Step 1對(duì)話框,如圖

5、7.2所示。圖7.2 MFC AppWizard Step 1對(duì)話框圖(3)選擇Single document單選按鈕。單擊What language would you like your resourses in?下拉列表框的下三角按鈕,選擇中文中國APPWZCHS.DLL選項(xiàng)。單擊Next按鈕,彈出MFC AppWizard Step 2 of 6對(duì)話框,如圖7.3所示。圖7.3 MFC AppWizard Step 2 of 6對(duì)話框(4)根據(jù)程序需要是否添加數(shù)據(jù)庫文件。在此選擇None單選按鈕。單擊Next按鈕,彈出MFC AppWizard Step 3 of 6對(duì)話框,如圖7.4

6、所示。圖7.4 MFC AppWizard Step 3 of 6對(duì)話框(5)根據(jù)需要選擇文檔所支持的功能。在此選擇None單選按鈕,單擊Next按鈕,彈出MFC AppWizard Step 4 of 6對(duì)話框,如圖7.5所示。圖7.5 MFC AppWizard Step 4 of 6對(duì)話框(6)根據(jù)需要選擇文檔的樣式。在此保留默認(rèn)設(shè)置,單擊Next按鈕,彈出MFC AppWizard Step 5 of 6對(duì)話框,如圖7.6所示。圖7.6 MFC AppWizard Step 5 of 6對(duì)話框(7)根據(jù)需要選擇工程樣式。如MFC使用形式等,在此保留默認(rèn)設(shè)置。單擊Next按鈕,彈出MFC

7、 AppWizard Step 6 of 6對(duì)話框,如圖7.7所示。圖7.7 MFC AppWizard Step 6 of 6對(duì)話框(8)在對(duì)話框中列出向?qū)傻念?,同時(shí)程序員可以改變類的基類,以實(shí)現(xiàn)新的功能。在此不改變基類。單擊Finish按鈕,彈出New Project Information對(duì)話框,如圖7.8所示。圖7.8 New Project Information對(duì)話框說明:改變CTestView類的基類為CEditView,就可以使應(yīng)用程序變?yōu)榭梢赃M(jìn)行輸入的文檔,形式就和記事本一樣。(9)該對(duì)話框中列出了新建立的應(yīng)用程序中項(xiàng)目的詳細(xì)信息,包括項(xiàng)目的類型、向?qū)?chuàng)建的類、文檔的樣

8、式特征,以及工程的目錄等。單擊OK按鈕,此時(shí)應(yīng)用程序向?qū)б呀?jīng)為用戶生成了一個(gè)可執(zhí)行的應(yīng)用程序框架。(10)選擇Build|Build test.exe命令。在信息輸出窗口顯示編譯結(jié)果如圖7.8.1所示。圖7.8.1 編譯結(jié)果(11)選擇Build|Execute test.exe命令,彈出無標(biāo)題-test文檔,如圖7.9所示。程序生成了一個(gè)文檔,單擊右上角關(guān)閉按鈕退出程序。雖然沒有編寫一行代碼,應(yīng)用程序向?qū)s創(chuàng)建了一個(gè)文檔應(yīng)用程序。在此基礎(chǔ)上就可以通過添加代碼實(shí)現(xiàn)特定功能。上面是創(chuàng)建單文檔應(yīng)用程序的基本步驟,如果需要?jiǎng)?chuàng)建一個(gè)基于多文檔的應(yīng)用程序,則只需要在利用向?qū)?chuàng)建應(yīng)用程序的第一步選擇Mul

9、tiple document。然后根據(jù)類向?qū)У奶崾旧梢粋€(gè)基于多文檔的應(yīng)用程序。圖7.9 執(zhí)行結(jié)果注意:一般來說不是面向數(shù)據(jù)的應(yīng)用或數(shù)據(jù)量很少的應(yīng)用程序,不宜采用文檔/視圖結(jié)構(gòu)。如一些工具程序包括磁盤掃描程序、時(shí)鐘程序,還有一些過程控制程序等。7.2.2 單文檔程序的核心消息傳遞在文檔、窗口被創(chuàng)建以后,整個(gè)應(yīng)用程序就開始進(jìn)入Windows的消息循環(huán)。前面已經(jīng)介紹了Windows的消息傳遞,當(dāng)由于文檔/視圖結(jié)構(gòu)將數(shù)據(jù)管理與顯示分離,其消息傳遞更為復(fù)雜。一般來說對(duì)于Windows標(biāo)準(zhǔn)消息,例如按下鍵盤或者單擊鼠標(biāo),這類消息將傳遞給框架窗口。文檔不會(huì)接收到此類消息,但是有些消息可能會(huì)被文檔類接收,這

10、就是WM_COMMAND消息和用戶界面更新。WM_COMMAND消息首先發(fā)送給活動(dòng)的視圖,然后發(fā)給視圖相應(yīng)的文檔和文檔模板對(duì)象。如果此時(shí)消息沒有被處理,那么消息會(huì)被傳遞到框架窗口和應(yīng)用程序?qū)ο筮M(jìn)行消息處理。7.3 文檔/視圖結(jié)構(gòu)分析文檔/視圖框架通過聯(lián)系幾個(gè)不同的類實(shí)現(xiàn)整個(gè)應(yīng)用程序。它們分別是應(yīng)用程序類CWinApp、框架窗口類CFrameWnd、視圖類CView、文檔類CDocument類和CDocTemplate類。下面對(duì)這幾個(gè)類進(jìn)行分析。7.3.1 主程序類CWinAppCWinApp類是主程序類,它負(fù)責(zé)進(jìn)程的啟動(dòng)、終止、消息循環(huán)和資源管理。在整個(gè)應(yīng)用程序中利用CWinApp的成員函數(shù)I

11、nitInstance()進(jìn)入MFC程序,同時(shí)其成員函數(shù)還包括消息循環(huán)、加載圖標(biāo)等。由于整個(gè)應(yīng)用程序框架已經(jīng)建立,對(duì)于CWinApp類一般不需要進(jìn)行改變。7.3.2 文檔類的基類CDocumentCDocument類是所有文檔類的基類,它提供了文檔類所需要進(jìn)行的最基本的操作,例如設(shè)置文檔標(biāo)題、建立新文檔、打開新文檔等。在CDocument類中最重要的兩個(gè)函數(shù)是SetModifiedFlag()和UpdateAllViews()。SetModifiedFlag()是設(shè)置一個(gè)標(biāo)志位,一般在文檔修改時(shí)調(diào)用該函數(shù)來設(shè)置一個(gè)標(biāo)志位,當(dāng)文檔關(guān)閉時(shí)提示用戶保存修改的內(nèi)容。UpdateAllViews()則刷

12、新所有和文檔關(guān)聯(lián)的視圖,以保證顯示的是最新內(nèi)容。CDocument常用函數(shù)如表7.1所示。表7.1 CDocument函數(shù)列表上面的函數(shù)中有些以虛函數(shù)的形式提供,可以重寫這些函數(shù)來提供CDocument類的派生類。函函 數(shù)數(shù) 名名說說 明明const CString& GetTitle() const獲得文檔標(biāo)題獲得文檔標(biāo)題virtual void SetTitle( LPCTSTR lpszTitle );設(shè)置文檔標(biāo)題設(shè)置文檔標(biāo)題const CString& GetPathName() const;獲得文檔數(shù)據(jù)文件的路徑獲得文檔數(shù)據(jù)文件的路徑virtual void SetP

13、athName(LPCTSTR lpszPathName,BOOL bAddToMRU = TRUE );設(shè)置文檔數(shù)據(jù)文件的路徑設(shè)置文檔數(shù)據(jù)文件的路徑virtual BOOL OnNewDocuMent()建立文檔建立文檔virtual BOOL OnOpenDocument()打開文檔打開文檔virtual void OnCloseDocument()關(guān)閉文檔關(guān)閉文檔virtual BOOL OnSaveDocument()保存文檔保存文檔virtual BOOL SaveModified()查詢文檔的修改狀態(tài)并保存修改后文檔查詢文檔的修改狀態(tài)并保存修改后文檔BOOL IsModified(

14、)確定文檔從最后一次存儲(chǔ)是否被修改過確定文檔從最后一次存儲(chǔ)是否被修改過void SetModifiedFlag( BOOL bModified = TRUE );設(shè)置文檔從最后一次存儲(chǔ)是否被修改過的布爾值設(shè)置文檔從最后一次存儲(chǔ)是否被修改過的布爾值7.3.3 文檔類CViewCView類提供了文檔類所需要的基本功能。此類可以獲得與視圖相關(guān)聯(lián)的文檔的指針,進(jìn)而獲得文檔中的數(shù)據(jù)。其類的常用函數(shù)如表7.2所示。表7.2 CView函數(shù)列表函函 數(shù)數(shù)說說 明明CDocument* GetDocument() const;獲得指向與視圖相關(guān)聯(lián)的文檔的指針獲得指向與視圖相關(guān)聯(lián)的文檔的指針BOOL DoPre

15、parePrinting( CPrintInfo* pInfo );打印預(yù)覽或準(zhǔn)備打印預(yù)覽或準(zhǔn)備virtual BOOL IsSelected( const CObject* pDocItem ) const;確定文檔是否被選中確定文檔是否被選中virtual void OnPrepareDC( CDC* pDC, CPrintInfo* pInfo = NULL );修改設(shè)備描述表修改設(shè)備描述表OnScroll():當(dāng)用戶滾動(dòng)時(shí),當(dāng)用戶滾動(dòng)時(shí),CView的響應(yīng)的響應(yīng)OnInitialUpdate():在類第一次構(gòu)造后由在類第一次構(gòu)造后由MFC調(diào)用調(diào)用OnDraw():由由MFC調(diào)用發(fā)出文檔到

16、設(shè)備描述表調(diào)用發(fā)出文檔到設(shè)備描述表OnUpdate():由由MFC調(diào)用對(duì)文檔的修改進(jìn)行響應(yīng)調(diào)用對(duì)文檔的修改進(jìn)行響應(yīng)在CView中最常用的函數(shù)是OnDraw():函數(shù),該函數(shù)在屏幕發(fā)生變化或因?yàn)榻裹c(diǎn)的變化需要重繪時(shí)調(diào)用。沒有該函數(shù),就不可能在程序切換后保證屏幕的正確顯示。若想在數(shù)據(jù)更新時(shí)強(qiáng)制視圖更新,可調(diào)用Invalidate()方法和UpdateWindow()方法來實(shí)現(xiàn)。注意:盡量不要在OnDraw之外的函數(shù)調(diào)用繪圖方法,那些方法不會(huì)在視圖需要重新繪制的時(shí)候被自動(dòng)調(diào)用。下面介紹CView類的一些派生類。CEditView:簡單的文本編輯器,類似Notepad。CListView:基于列表的視

17、圖,類似文件夾瀏覽。CTreeView:基于樹狀控件的視圖,類似文件瀏覽左側(cè)的樹狀結(jié)構(gòu)。CRichEditView:支持多種字體、OLE和RTF格式的高級(jí)編輯器。CScrollView:支持滾動(dòng)條視圖。CFormView:窗體視圖,支持在上邊使用對(duì)話框控件。CRecordView:連接到ODBC數(shù)據(jù)庫的視圖。CDaoRecordView:連接到DAO數(shù)據(jù)庫的視圖??梢栽谑纠?.1中的第(8)步進(jìn)行設(shè)置,當(dāng)選擇相應(yīng)的類后,可以使得文檔程序擁有相應(yīng)的功能。7.3.4 文檔模板類CDocTemplateCDocTemplate類是文檔模板,它將獨(dú)立的文檔、視圖和框架窗口對(duì)象聯(lián)系在一起。在文檔/視圖結(jié)

18、構(gòu)中,將文檔、視圖和框架聯(lián)系在一起的對(duì)象是CDocTemplate。在SDI中是CSingleDocTemplate,而在MDI中是CMultiDocTemplate,這兩個(gè)類都是CDocTemplate的子類。CDocTemplate類中的常用函數(shù)如表7.3所示。表7.3 CDocTemplate類函數(shù)列表函函 數(shù)數(shù)說說 明明virtual BOOL GetDocString( CString& rString, enum DocStringIndex index ) const;獲得與文檔相關(guān)的字符串獲得與文檔相關(guān)的字符串virtual void LoadTemplate();加載

19、指定模板加載指定模板virtual void AddDocument( CDocument* pDoc );給文檔模板添加指定的模板給文檔模板添加指定的模板virtual void RemoveDocument( CDocument* pDoc );在文檔模板列表中輸出文檔在文檔模板列表中輸出文檔virtual CDocument* CreateNewDocument();建立文檔建立文檔virtual BOOL SaveAllModified();查詢文檔模板的修改狀態(tài)并存儲(chǔ)與之有關(guān)查詢文檔模板的修改狀態(tài)并存儲(chǔ)與之有關(guān)的文檔的文檔virtual void CloseAllDocuments(

20、BOOL bEndSession );關(guān)閉所有文檔關(guān)閉所有文檔virtual void SetDefaultTitle( CDocument* pDocument ) = 0; 設(shè)置文檔默認(rèn)標(biāo)題設(shè)置文檔默認(rèn)標(biāo)題文檔、視圖和框架三者之間是互相關(guān)聯(lián)的,它們之間的關(guān)聯(lián)通過CDocTemplate類來實(shí)現(xiàn)。CDocTemplate的構(gòu)造函數(shù)定義如下:CDocTemplate ( UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass );從構(gòu)造函數(shù)可以看出,它將文

21、檔類、框架類和視圖類聯(lián)系在一起,使得原本獨(dú)立的類相互協(xié)調(diào),完成整個(gè)應(yīng)用程序。7.3.5 框架窗口類CFrameWndCFrameWnd類主要負(fù)責(zé)框架窗口的維護(hù)工作,例如工具欄、菜單、狀態(tài)欄的顯示和更新。該類的常用的成員函數(shù)如表7.4所示。表7.4 CFrameWnd類函數(shù)列表在SDI中使用的是CFrameWnd,而在MDI中使用的是CMDIFrameWnd和CMDIChildWnd。函函 數(shù)數(shù)說說 明明BOOL Create();創(chuàng)建窗口的方法,可以重載來改變屬性創(chuàng)建窗口的方法,可以重載來改變屬性virtual BOOL LoadFrame();從資源加載框架從資源加載框架void Initi

22、alUpdateFrame( CDocument* pDoc, BOOL bMake Visible );調(diào)用所有關(guān)聯(lián)的視圖的調(diào)用所有關(guān)聯(lián)的視圖的OnInitialUpdate()void SetActiveView( CView* pViewNew, BOOL bNotify = TRUE );激活一個(gè)視圖激活一個(gè)視圖CView* GetActiveView() const;獲取當(dāng)前激活視圖獲取當(dāng)前激活視圖CWnd* CreateView( CCreateContext* pContext, UINT nID = AFX_IDW_PANE_FIRST );創(chuàng)建一個(gè)視圖創(chuàng)建一個(gè)視圖virtua

23、l CDocument* GetActiveDocument();獲取當(dāng)前激活文檔獲取當(dāng)前激活文檔void SetMessageText( LPCTSTR lpszText );void SetMessageText( UINT nID );在狀態(tài)欄顯示一條消息在狀態(tài)欄顯示一條消息7.4 單文檔程序分析前面介紹了文檔/視圖中常用的類,本節(jié)對(duì)利用應(yīng)用程序向?qū)傻腟DI程序進(jìn)行分析。在單文檔應(yīng)用程序中,程序的大部分初始化工作在MFC程序的入口函數(shù)InitInstance()中實(shí)現(xiàn)。它負(fù)責(zé)進(jìn)入MFC程序,并且進(jìn)入消息循環(huán),直到收到退出消息而退出程序。7.4.1 從基本概念開始7.3節(jié)已經(jīng)介紹了單文

24、檔中用到的幾個(gè)類,并且介紹了這些類的主要成員。在文檔/視圖模型中利用類構(gòu)成了整個(gè)系統(tǒng)框架。下面首先簡單分析一下應(yīng)用程序構(gòu)建的基本過程。先來分析InitInstance()函數(shù)中的工作。(1)在MFC框架程序中,向?qū)Ф紩?huì)創(chuàng)建一個(gè)全局變量,即CWinApp對(duì)象theApp。例如例7.1中的全局變量的定義如下:CTestApp theApp;(2)在CTestApp類的InitInstance()函數(shù)中進(jìn)行初始化工作。其中動(dòng)態(tài)創(chuàng)建文檔模板pDocTemplate,在動(dòng)態(tài)創(chuàng)建文檔、視圖和框架的時(shí)候文檔模板將三者綁定在一起。01CSingleDocTemplate* pDocTemplate;02pDo

25、cTemplate = new CSingleDocTemplate(03IDR_MAINFRAME,04RUNTIME_CLASS(CTestDoc),05RUNTIME_CLASS(CMainFrame), / main SDI frame window06RUNTIME_CLASS(CTestView)07);(3)利用下面語句將單文檔模板添加到模板鏈表中。AddDocTemplate(pDocTemplate);(4)執(zhí)行MFC框架的命令行參數(shù),創(chuàng)建空白文檔窗口。CCommandLineInfo cmdInfo;ParseCommandLine(cmdInfo);(5)將文檔、視圖和框

26、架進(jìn)行初始化,如果失敗則返回。if (!ProcessShellCommand(cmdInfo)return FALSE;(6)顯示窗口,更新客戶區(qū)視窗并進(jìn)入消息循環(huán)。m_pMainWnd-ShowWindow(SW_SHOW);m_pMainWnd-UpdateWindow();通過分析上面的每一小段程序可以看到,整個(gè)SDI程序是利用模板將文檔、視圖和框架綁定在一起,然后進(jìn)行必要的初始化后,程序進(jìn)入消息循環(huán)。在成員程序中,文檔、視圖和框架利用這種綁定關(guān)系進(jìn)行交互從而完成數(shù)據(jù)的處理與顯示,協(xié)調(diào)整個(gè)應(yīng)用程序。注意:文檔/視圖結(jié)構(gòu)并沒有完全要求所有數(shù)據(jù)都屬于文檔類,視圖類也可以有自己的數(shù)據(jù)。如果在

27、視圖類中不定義任何數(shù)據(jù),在需要時(shí)都從文檔類中獲取,這樣做會(huì)影響程序的效率。7.4.2 理解應(yīng)用程序在使用向?qū)?chuàng)建了基于單文檔的應(yīng)用程序之后,向?qū)?huì)自動(dòng)生成整個(gè)文檔/視圖模型所需要的類,并且將這些類緊密地聯(lián)系在一起。在7.4.1節(jié)已經(jīng)看到了在InitInstance()函數(shù)中所進(jìn)行的初始化工作。在單文檔中利用各個(gè)類對(duì)各部分進(jìn)行管理和操作,下面分別介紹每一個(gè)類具體實(shí)現(xiàn)的過程,從而分析整個(gè)應(yīng)用程序。1CAboutDlg類這是關(guān)于對(duì)話框的類,在利用Visual C+向?qū)蓪?duì)話框、單文檔和多文檔應(yīng)用程序時(shí),向?qū)?huì)默認(rèn)的生成一個(gè)“關(guān)于”對(duì)話框,并且自動(dòng)建立了一個(gè)消息映射。在標(biāo)題欄上右擊,選擇彈出的快捷菜

28、單的“關(guān)于”命令,就會(huì)彈出該對(duì)話框。該類的聲明在Test.cpp中實(shí)現(xiàn),代碼如下: 上面的代碼是CAboutDlg類的聲明及成員函數(shù)的實(shí)現(xiàn),并且該對(duì)話框擁有自己的消息映射。用戶可以在上面添加控件,并且為控件建立消息映射等。2CMainFrame 類CMainFrame 類是從CFrameWnd派生出來的類。該類作為單文檔應(yīng)用程序的主框架窗口,其聲明如下:上面是CMainFrame類的聲明,該類擁有聲明DECLARE_DYNCREATE(CMainFrame)支持動(dòng)態(tài)創(chuàng)建。同時(shí)使用AssertValid()和Dump()函數(shù)進(jìn)行調(diào)試版本的診斷和合法性驗(yàn)證。在該類中擁有成員變量m_wndStatu

29、sBar和m_wndToolBar,負(fù)責(zé)在對(duì)狀態(tài)欄和工具欄進(jìn)行管理和顯示等。PreCreateWindow()函數(shù)在窗口將被創(chuàng)建時(shí)調(diào)用,可以對(duì)窗口的樣式進(jìn)行修改等。OnCreate()函數(shù)響應(yīng)在窗口創(chuàng)建時(shí)發(fā)送的WM_CREATE消息??梢钥吹皆摵瘮?shù)主要實(shí)現(xiàn)狀態(tài)欄和工具欄的顯示等。關(guān)于如何實(shí)現(xiàn)這些函數(shù),讀者可以查看類成員函數(shù)的具體代碼,在此不再介紹。注意:如果想在創(chuàng)建應(yīng)用程序后改變相關(guān)的外觀,則需要直接編輯CMain Frame:PreCreate Window()函數(shù)。直接編輯還允許為應(yīng)用程序的初始外觀作某些額外的變化。3CTestDoc類CTestDoc類是從CDocument派生出來的類,

30、是應(yīng)用程序文檔類,該類的函數(shù)聲明如下:CTestDoc類大部分內(nèi)容和CMainFrame類基本相同,同時(shí)提供了動(dòng)態(tài)創(chuàng)建、調(diào)試版本的診斷和合法性驗(yàn)證等內(nèi)容。不過該類提供了兩個(gè)函數(shù)OnNewDocument()和Serialize(CArchive& ar)函數(shù)。OnNewDocument()函數(shù)負(fù)責(zé)新建一個(gè)文檔,Serialize(CArchive& ar)函數(shù)支持了串行化處理。關(guān)于串行化處理將在7.5節(jié)進(jìn)行介紹。說明:在向?qū)ё詣?dòng)生成的單文檔應(yīng)用程序中會(huì)自動(dòng)生成一些菜單命令,在選擇“文件”|“打開”和“文件”|“保存”命令時(shí)會(huì)調(diào)用Serialize()函數(shù)。但此時(shí)的Seriali

31、ze()函數(shù)并沒有進(jìn)行數(shù)據(jù)的保存,因此不能實(shí)現(xiàn)數(shù)據(jù)在磁盤的存取。4CTestView類CTestView類是從CView派生出來的類。該類負(fù)責(zé)整個(gè)窗口的顯示操作。對(duì)于一個(gè)顯示的窗口,要改變其顯示的內(nèi)容則該類是必不可少的,其提供了一系列的操作支持窗口的刷新等。該類的聲明如下:CTestView類負(fù)責(zé)窗口顯示,該類與上面介紹的類一樣,支持動(dòng)態(tài)創(chuàng)建、調(diào)試版本的診斷和合法性驗(yàn)證等。同時(shí)該類中提供了OnPreparePrinting(CPrintInfo* pInfo)函數(shù)、OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)函數(shù)和OnEndPrinting(CDC*

32、 pDC, CPrintInfo* pInfo)函數(shù),這三個(gè)函數(shù)負(fù)責(zé)進(jìn)行打印工作。該類同時(shí)提供了GetDocument()函數(shù),用來得到指向與視圖相關(guān)聯(lián)的文檔的指針。在文檔/視圖模型中這個(gè)函數(shù)是非常重要的,因?yàn)槲臋n/視圖的基本概念就是將數(shù)據(jù)的存儲(chǔ)和顯示分開。數(shù)據(jù)的存儲(chǔ)一般在在CDocument的派生類中進(jìn)行串行化存儲(chǔ)。數(shù)據(jù)的顯示在CView中實(shí)現(xiàn)。因此得到與視圖相關(guān)聯(lián)的文檔的指針是數(shù)據(jù)顯示的前提。5CTestApp類CTestApp類是應(yīng)用程序?qū)ο箢?,?.4.1節(jié)已經(jīng)介紹了在該類的InitInstance()函數(shù)中將各個(gè)類進(jìn)行聯(lián)系,創(chuàng)建窗口并進(jìn)入消息循環(huán)的基本過程。該類的聲明非常簡單,如下所

33、示。上面是CTestApp類的聲明部分,可以看到該類的成員函數(shù)包括InitInstance()函數(shù),利用該函數(shù)可實(shí)現(xiàn)整個(gè)應(yīng)用程序的初始化工作。同時(shí)該類還擁有一個(gè)成員函數(shù)OnAppAbout()函數(shù),該函數(shù)是單擊“關(guān)于”命令的消息響應(yīng)函數(shù),實(shí)現(xiàn)“關(guān)于”對(duì)話框的彈出。上面介紹了整個(gè)單文檔應(yīng)用程序中使用的5個(gè)類。整個(gè)應(yīng)用程序使用應(yīng)用程序類進(jìn)行整個(gè)應(yīng)用程序的工作。而數(shù)據(jù)的存儲(chǔ)使用文檔類,數(shù)據(jù)的顯示使用視圖類。應(yīng)用程序主框架類將數(shù)據(jù)的顯示和數(shù)據(jù)的管理兩個(gè)類聯(lián)系在一起。在單文檔應(yīng)用程序中使用類的形式封裝了整個(gè)程序的操作,充分體現(xiàn)了面向?qū)ο蟮奶攸c(diǎn)。說明:應(yīng)用程序?qū)ο蟮某蓡T函數(shù)CWinApp:OnFileNe

34、w()在選擇File菜單的New命令時(shí)被調(diào)用,默認(rèn)時(shí)在InitInstance()中也會(huì)被調(diào)用。原理是在InitInstance()中有一個(gè)命令行參數(shù)的執(zhí)行過程。當(dāng)命令行上沒有參數(shù)時(shí),函數(shù)ParseCommandLine(cmdInfo)會(huì)調(diào)用CCommandLineInfo : 把m_nShellCommand成員設(shè)置為CCommandLineInfo: FileNew,這導(dǎo)致ProcessShellCommand()成員函數(shù)調(diào)用OnFileNew()。用戶可在InitInstance()中顯式的調(diào)用OnFileNew()。7.5 文 檔 操 作在文檔類應(yīng)用程序中經(jīng)常會(huì)對(duì)文檔進(jìn)行一些必要的操

35、作,例如實(shí)現(xiàn)數(shù)據(jù)在磁盤的保存,或者添加打開新文檔的功能等,這些都是利用一些常用的文檔操作實(shí)現(xiàn)的。本節(jié)介紹實(shí)現(xiàn)數(shù)據(jù)保存和消息映射的幾類操作。7.5.1 串行化處理程序設(shè)計(jì)中,經(jīng)常需要把用戶的文檔數(shù)據(jù)長期的保存在磁盤中。MFC提供了串行化的機(jī)制實(shí)現(xiàn)對(duì)象輸入到字節(jié)流,或者從字節(jié)流中讀出對(duì)象。當(dāng)關(guān)閉文檔后,它可以將數(shù)據(jù)存儲(chǔ)在磁盤中,同時(shí)串行化的操作也支持網(wǎng)絡(luò)和串口的傳輸。在SDI應(yīng)用程序中,讀者可以看到這樣一段代碼:01void CTestDoc:Serialize(CArchive& ar)0203if (ar.IsStoring()0405/ TODO: add storing code

36、here0607else0809/ TODO: add loading code here1011這段代碼是實(shí)現(xiàn)串行化的部分。它利用CArchive類實(shí)現(xiàn)串行化處理。串行化處理中。如果需要對(duì)一個(gè)新建類實(shí)現(xiàn)串行化,則需要增加串行化操作機(jī)制,即需要為新建類添加串行化語句,同時(shí)在文檔類中添加對(duì)象數(shù)組的序列化操作。在7.6節(jié)和7.6節(jié)的例子中可以看到串行化處理的詳細(xì)步驟。7.5.2 消息映射MFC的ClassWizard可以為類添加消息映射,但是有些類并不可以利用ClassWizard來添加,需要用戶手動(dòng)添加消息映射。因此下面介紹消息映射的知識(shí)。消息映射就是用來確定消息到來時(shí)哪個(gè)函數(shù)去處理的一個(gè)映射集

37、合。實(shí)際中消息映射是一個(gè)數(shù)組,它記錄了消息的全部信息,例如消息是誰發(fā)送的,消息的參數(shù),消息的處理函數(shù)等。例如SDI程序中的消息映射如下:01BEGIN_MESSAGE_MAP(CTestApp, CWinApp)02/AFX_MSG_MAP(CTestApp)03ON_COMMAND(ID_APP_ABOUT, OnAppAbout)04/ NOTE - the ClassWizard will add and remove mapping macros here.05/ DO NOT EDIT what you see in these blocks of generated code!06

38、/AFX_MSG_MAP07/ Standard file based document commands08ON_COMMAND(ID_FILE_NEW, CWinApp:OnFileNew)09ON_COMMAND(ID_FILE_OPEN, CWinApp:OnFileOpen)10/ Standard print setup command11ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp:OnFilePrintSetup)12END_MESSAGE_MAP()位于AFX_MSG_MAP之間的宏是由ClassWizard生成的,用戶添加時(shí)應(yīng)該把消息映射添

39、加在AFX_MSG_MAP后面。添加消息映射完成后,就需要在相應(yīng)的類中聲明該函數(shù),同時(shí)定義函數(shù)。7.5.3 消息傳遞通過前面的介紹可以發(fā)現(xiàn),文檔/視圖結(jié)構(gòu)的類之間利用模板進(jìn)行綁定,消息的傳遞十分復(fù)雜。下面對(duì)消息傳遞過程進(jìn)行介紹。當(dāng)用戶選擇菜單命令時(shí),消息首先傳遞給當(dāng)前的視圖,然后傳遞給當(dāng)前文檔,再傳遞給當(dāng)前模板,然后傳給框架窗口,最后傳給應(yīng)用程序。如果消息在傳遞過程中被處理,那么消息將不再繼續(xù)傳遞。在文檔/視圖應(yīng)用程序中,經(jīng)常需要利用視圖類顯示圖形數(shù)據(jù),而在文檔類中保存數(shù)據(jù),那么兩者之間如何聯(lián)系,又是什么時(shí)候進(jìn)行聯(lián)系的呢?在文檔類中,經(jīng)常添加數(shù)據(jù)成員以保存數(shù)據(jù),有時(shí)在視圖類中獲取到數(shù)據(jù)以后需要

40、利用傳遞給文檔類的數(shù)據(jù)成員。這時(shí),可以利用this-GetDocument()得到當(dāng)前文檔對(duì)象的指針,然后訪問其數(shù)據(jù)成員,保存數(shù)據(jù)。有時(shí)需要把數(shù)據(jù)顯示在用戶的工作區(qū)上,例如圖形的顯示問題。一般來說圖形的顯示處理函數(shù)需要放在CTestView:OnDraw()函數(shù)里,這是為了解決圖形的刷新和重繪問題。關(guān)于圖形的刷新和重繪將在第10章進(jìn)行介紹。在CTestView:OnDraw()函數(shù)里需要得到文檔類的數(shù)據(jù)時(shí),可仍然利用this-Get Document()得到其對(duì)象的指針,然后進(jìn)行數(shù)據(jù)的訪問。7.6 SDI應(yīng)用程序?qū)崙?zhàn)前面介紹了文檔/視圖結(jié)構(gòu)的基本原理,本節(jié)結(jié)合實(shí)例講解SDI程序設(shè)計(jì)的一般步驟。

41、【示例7.2】 編寫一個(gè)SDI應(yīng)用程序,可以在視圖窗口輸入個(gè)人信息,并實(shí)現(xiàn)保存功能。操作步驟如下所述。(1)根據(jù)示例7.1創(chuàng)建基于單文檔的應(yīng)用程序,并在第(8)步改變CTestView類的基類為CFormView。(2)在資源上添加控件并設(shè)置控件的ID和標(biāo)題如表7.5所示。表7.5 控件列表程序運(yùn)行效果如圖7.10所示??乜?件件 類類 型型控控 件件 標(biāo)標(biāo) 題題IDStatic Text姓名IDC_STATICEdit Box IDC_nameStatic Text性別IDC_STATICEdit Box IDC_sexStatic Text學(xué)號(hào)IDC_STATICEdit Box IDC_

42、numStatic Text年齡IDC_STATICEdit Box IDC_ageStatic Text家庭住址IDC_STATICEdit Box IDC_addStatic Text聯(lián)系電話聯(lián)系電話IDC_STATICEdit Box IDC_telGroup Box數(shù)據(jù)操作IDC_STATICButton保存IDC_saveButton取消IDC_undoGroup Box數(shù)據(jù)瀏覽IDC_STATICButton上一個(gè)IDC_lastButton下一個(gè)下一個(gè)IDC_next圖7.10 運(yùn)行效果圖(3)利用類向?qū)榭丶砑訑?shù)據(jù)成員,本例中需要為所有的編輯框控件添加數(shù)據(jù)成員,如圖7.11所

43、示。圖7.11 添加數(shù)據(jù)成員(4)利用類向?qū)榘粹o控件單擊添加響應(yīng)函數(shù)。保留默認(rèn)函數(shù)名。(5)利用類向?qū)砑宇怌Student,類可以從CObject的任何派生類繼承,例子中選擇了CEdit派生。這樣可以使類進(jìn)行串行化操作。在類CStudent類中添加變量如下所示。public: /在類中添加變量,實(shí)現(xiàn)數(shù)據(jù)保存CStringadd;/家庭住址intage;/年齡CStringname;/姓名intnum;/學(xué)號(hào)CStringsex;/性別CStringtel;/電話號(hào)碼編寫函數(shù)Serialize(CArchive& ar)函數(shù)如下所示。01void CStudent:Serialize

44、(CArchive& ar) 0203/串行化操作04if (ar.IsStoring()05/ storing code06araddagenamenumsexaddagenamenumsextel;/從文件中讀取1112(6)在類CTestDoc.h 中添加數(shù)據(jù)成員如下:#define N 33CStudent studentN;/對(duì)象數(shù)組即添加一個(gè)對(duì)象數(shù)組,且數(shù)組大小為33個(gè),即最多可以添加33名學(xué)生的信息。注意:將類CStudent的頭文件包含進(jìn)testDoc.h中,即添加語句:#include student.h(7)利用類向?qū)砑訂螕簟氨4妗卑粹o的消息映射,編寫代碼如下:

45、(8)上面的代碼是得到控件的值,然后保存在數(shù)組的相應(yīng)位置。再利用類向?qū)砑訂螕簟叭∠卑粹o的消息映射,編寫代碼如下:(9)單擊“取消”按鈕即把所有控件的值清空。上面利用變量和控件之間的關(guān)系,即利用了DDX數(shù)據(jù)傳遞機(jī)制。再利用類向?qū)砑訂螕簟跋乱粋€(gè)”按鈕的消息映射,編寫代碼如下:(10)上面的代碼是根據(jù)當(dāng)前位置得到上一個(gè)位置,然后根據(jù)數(shù)組的內(nèi)容查看上一個(gè)位置的相關(guān)變量,利用DDX機(jī)制顯示在編輯框中。再利用類向?qū)砑訂螕簟跋乱粋€(gè)”按鈕的消息映射,編寫代碼如下:(11)在上面的操作中都是利用數(shù)組的數(shù)據(jù)進(jìn)行查看的,數(shù)據(jù)的處理在CTestDoc中,因此添加語句CTestDoc *pdoc=GetDocu

46、ment();。然后把數(shù)據(jù)保存在對(duì)象數(shù)組中,在CTestDoc中進(jìn)行串行化處理,即在void CTestDoc:Serialize(CArchive& ar)添加語句實(shí)現(xiàn)學(xué)生對(duì)象數(shù)組的串行化處理。(12)編譯、連接,運(yùn)行程序,結(jié)果如圖7.12所示。添加數(shù)據(jù)后,單擊“保存”按鈕。再次添加另一學(xué)生的信息,單擊“保存”按鈕。選擇“文件”|“保存”命令,彈出保存為對(duì)話框,如圖7.13所示。輸入文件名,選擇目錄后,單擊“保存”按鈕。圖7.12 添加數(shù)據(jù)圖圖7.13 保存為對(duì)話框(13)退出應(yīng)用程序后,再次運(yùn)行。選擇“文件”|“打開”命令,彈出打開對(duì)話框。找到剛保存的文件后,單擊“打開”按鈕,此時(shí)

47、程序已經(jīng)打開文件。查找到31號(hào)學(xué)生的信息,如圖7.14所示,單擊“上一個(gè)”按鈕,查找到30號(hào)學(xué)生的信息,如圖7.15所示。圖7.14 學(xué)生信息1圖7.15 學(xué)生信息2上面的例子完整地介紹了單文檔應(yīng)用程序的開發(fā),講解了文檔中的常見操作,對(duì)串行化處理進(jìn)行了重點(diǎn)分析。在實(shí)際的應(yīng)用中,維護(hù)對(duì)象數(shù)組是比較困難的,在下面的章節(jié)中將采用MFC中的集合類再次討論串行化的應(yīng)用。7.7 MFC的集合類與字符串類在7.6節(jié)中采用了數(shù)組這一數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)數(shù)據(jù)。實(shí)際上MFC中提供了一些集合類以實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)和管理,從而使得對(duì)數(shù)據(jù)的存儲(chǔ)更加方便,同時(shí)可以提高存儲(chǔ)效率和節(jié)省存儲(chǔ)空間。本節(jié)對(duì)MFC的集合類進(jìn)行介紹。7.7.1

48、集合類介紹MFC類庫的集合類包含了3種數(shù)據(jù)結(jié)構(gòu),分別是動(dòng)態(tài)鏈表、動(dòng)態(tài)數(shù)組和字典。動(dòng)態(tài)鏈表提供有序的、非索引的雙向鏈表。它有頭、尾指針,可以從頭或者尾部增加、刪除元素,也可以在中間插入元素。動(dòng)態(tài)數(shù)組則提供了一個(gè)大小可變的、整數(shù)索引的對(duì)象數(shù)組。字典則是把一個(gè)關(guān)鍵字與對(duì)象關(guān)聯(lián)起來的集合。集合類非常適用于數(shù)據(jù)結(jié)構(gòu)的操作,簡化了用戶對(duì)數(shù)據(jù)結(jié)構(gòu)的構(gòu)造及組織過程。在文檔/視圖這一將數(shù)據(jù)的管理和顯示分離開來的結(jié)構(gòu)中,利用集合類可以有效地實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)和管理,簡化操作。MFC的集合類分為模板和非模板類兩種。模板類提供了較好的數(shù)據(jù)類型,在MFC中對(duì)3種集合類的模板類封裝如下所示。數(shù)組:CtypedPtrArray

49、;鏈表:CtypedPtrlist;字典:CTypedPtrMap。7.7.2 CTypedPtrList模板鏈表類CTypedPtrList模板鏈表類的原型如下:templateclass CTtypedPtrList:public BASE_CLASS模板參數(shù)BASE_CLASS是指向鏈表類的CObList或者CPtrList類型,TYPE代表存儲(chǔ)在基類鏈表中的元素類型。CTypedPtrList的成員函數(shù)如表7.6所示。表7.6 CTypedPtrList的成員函數(shù)注意:BASE_CLASS只能是CObList或者CPtrList類型,其他都不可以。函函 數(shù)數(shù)說說 明明TYPE GetH

50、ead() const;獲得鏈表頭元素獲得鏈表頭元素TYPE GetTail() const;獲得鏈表尾元素獲得鏈表尾元素TYPE RemoveHead();從鏈表的頭部刪除元素,返回此元素從鏈表的頭部刪除元素,返回此元素TYPE RemoveTail();從鏈表尾刪除,返回此元素從鏈表尾刪除,返回此元素POSITION AddHead( TYPE newElement );在頭部添加新元素在頭部添加新元素POSITION AddTail( TYPE newElement );從尾部添加新元素從尾部添加新元素TYPE& GetNext( POSITION& rPosition

51、);獲取下一個(gè)位置獲取下一個(gè)位置TYPE& GetPrev(POSITION& rPosition );獲取前一個(gè)位置獲取前一個(gè)位置【示例7.3】 模板鏈表類的基本操作。下面的代碼實(shí)現(xiàn)了使用模板鏈表類進(jìn)行數(shù)據(jù)的基本操作。首先定義一個(gè)類,然后利用輸入數(shù)據(jù)對(duì)類的數(shù)據(jù)成員進(jìn)行初始化。然后利用模板鏈表類實(shí)現(xiàn)數(shù)據(jù)的保存。在結(jié)束后輸出模板鏈表中保存的數(shù)據(jù)。具體操作步驟如下所述。(1)創(chuàng)建一個(gè)基于控制臺(tái)的應(yīng)用程序。并且添加MFC的支持。方法是選擇Project|Settings命令,彈出Project Settings對(duì)話框,在General標(biāo)簽下的“Microsoft Foundation

52、 Classes:”下拉列表框中選擇Use MFC in Shared DLL項(xiàng)。此時(shí)即添加了MFC動(dòng)態(tài)鏈接庫。(2)在代碼編輯區(qū)域輸入代碼如下:分析:上面的程序就是利用模板鏈表類實(shí)現(xiàn)數(shù)據(jù)的保存。這樣大大簡化了對(duì)鏈表的各種處理。該類提供了大量的成員函數(shù)可以方便地進(jìn)行數(shù)據(jù)的存儲(chǔ)和讀取。上面的例子介紹了使用模板鏈表類的基本方法。使用模板鏈表類可以方便地進(jìn)行數(shù)據(jù)的存儲(chǔ)和讀取。7.7.3 字符串類在C+語言中對(duì)字符串的處理是以字符數(shù)組的形式進(jìn)行的。因此在進(jìn)行字符串的操作中經(jīng)常需要逐個(gè)檢查各個(gè)元素等。而在MFC中對(duì)字符串的操作進(jìn)行了封裝,出現(xiàn)了一個(gè)MFC類:CString類。使得在MFC應(yīng)用程序中對(duì)字符

53、串的操作變得非常方便。CString類是單獨(dú)提供的類,該類沒有基類,它提供了對(duì)字符串操作的封裝工作。該類的常用成員函數(shù)如表7.7所示。表7.7 CString類的成員函數(shù)函函 數(shù)數(shù)說說 明明int GetLength() const;獲取字符串長度獲取字符串長度BOOL IsEmpty() const;判斷字符串是否為空判斷字符串是否為空void Empty();清空字符串清空字符串TCHAR GetAt( int nIndex ) const;得到某一位置的字符得到某一位置的字符void SetAt( int nIndex, TCHAR ch );設(shè)置某一位置的字符設(shè)置某一位置的字符CStr

54、ing Left( int nCount ) const;得到左側(cè)的得到左側(cè)的nCount個(gè)字符組成的字符串個(gè)字符組成的字符串CString Right( int nCount ) const;得到右側(cè)的得到右側(cè)的nCount個(gè)字符組成的字符串個(gè)字符組成的字符串void TrimLeft();清空左側(cè)空格清空左側(cè)空格void TrimRight();清空右側(cè)空格清空右側(cè)空格void ReleaseBuffer( int nNewLength = 1 );釋放字符串釋放字符串BOOL LoadString( UINT nID );加載字符串加載字符串說明:CString類的定義在afx.h中,如

55、果需要使用該類,則需要添加語句#include 。如果建立的是基于MFC的工程就不用包含此頭文件,因?yàn)橄到y(tǒng)已經(jīng)包含了此文件。同時(shí)如果在控制臺(tái)應(yīng)用程序中使用該類,必須添加MFC的支持?!臼纠?.4】 字符串的基本操作。下面的代碼實(shí)現(xiàn)了字符串的基本操作。具體的操作步驟如下:(1)在C+源文件中添加代碼,實(shí)現(xiàn)對(duì)字符串的操作,代碼如下:上面的過程是利用CString類對(duì)字符串進(jìn)行處理,在使用CString對(duì)字符串進(jìn)行處理的過程中,只要合理利用其類的成員函數(shù)就可以方便地進(jìn)行字符串的操作。上面介紹了CString類的使用,在MFC應(yīng)用程序中經(jīng)常需要輸入輸出字符串。使用CString類可以方便地進(jìn)行字符串的

56、處理。7.8 MDI應(yīng)用程序在Visual C+中可以利用向?qū)?chuàng)建基于單文檔和多文檔的應(yīng)用程序。雖然基于多文檔的應(yīng)用程序和單文檔應(yīng)用程序有很多相似性,但兩者之間在使用上還有很多區(qū)別。本節(jié)首先對(duì)多文檔應(yīng)用程序進(jìn)行分析,然后給出一個(gè)應(yīng)用實(shí)例。7.8.1 MDI應(yīng)用程序分析利用向?qū)?chuàng)建基于多文檔的應(yīng)用程序,可以看到它與單文檔應(yīng)用程序有很多區(qū)別。例如它可以打開多個(gè)文檔,甚至說可以打開不同類型的文檔。在Visual C+中可以看到生成的類也有所不同。在多文檔應(yīng)用程序中會(huì)生成一個(gè)CMainFrame類,且其父類為CMDIFrameWnd類,還會(huì)生成CChildFrame類,其父類為CMDIChildWnd

57、類。CMDIFrameWnd類是應(yīng)用程序主框架窗口類,而CMDIChildWnd類是應(yīng)用程序子框架窗口類。一個(gè)應(yīng)用程序的主框架窗口并不是與當(dāng)前的視圖和文檔相關(guān)聯(lián),因此必須得到當(dāng)前的活動(dòng)子窗口,也就是子框架窗口,然后通過該子窗口獲取相關(guān)的視圖和文檔。在SDI程序中,主框架窗口就是文檔框窗,可以采用以下方法取得當(dāng)前文檔和視圖。取得活動(dòng)文檔:CMyDocument* pDoc;pDoc=(CMyDocument*)(CFrameWnd*)AfxGetApp()-m_pMainWnd)-GetActiveDocument();或pDoc=(CMyDocument*)(CFrameWnd*)AfxGet

58、MainWnd();取得活動(dòng)視圖:CMyView* pView;pView=(CMyView*)(CFrameWnd*)AfxGetApp()-m_pMainWnd)-GetActiveView();對(duì)于MDI程序,由于子窗口才是文檔框窗,因此首先要用GetActiveFrame()取得活動(dòng)子框架窗口,然后通過該子窗口獲取活動(dòng)文檔和視圖。CMDIChildWnd* pChild=(CMDIChildWnd*)(CFrameWnd*)AfxGetApp()-m_pMainWnd)-GetActiveFrame();/取得活動(dòng)文檔:CMyDocument* pDoc=pChild-GetActiv

59、eDocument();CMyView* pView=(CMyView*)pChild-GetActiveView();通過上面的分析可以看到,整個(gè)多文檔應(yīng)用程序與單文檔應(yīng)用程序的區(qū)別就在于,它利用了主框架窗口和子框架窗口進(jìn)行了整個(gè)應(yīng)用程序和當(dāng)前的文檔和視圖之間的聯(lián)系。在下面將會(huì)看到一個(gè)多文檔的應(yīng)用實(shí)例。7.8.2 MDI應(yīng)用實(shí)例MDI和SDI有著相同的基本框架,MDI擁有子框架窗口,可以打開多個(gè)文檔。本節(jié)介紹基本的多文檔程序?qū)嵗??!臼纠?.5】 創(chuàng)建MDI應(yīng)用程序,實(shí)現(xiàn)利用鼠標(biāo)繪制矩形程序,并實(shí)現(xiàn)保存功能。操作步驟如下所述。(1)利用向?qū)?chuàng)建一個(gè)多文檔的應(yīng)用程序。(2)在CTestView.

60、h中添加數(shù)據(jù)成員。CPoint start;/定義對(duì)象CPoint end;這是保存鼠標(biāo)按下和彈起的坐標(biāo),實(shí)現(xiàn)畫圖功能。并且在構(gòu)造函數(shù)中初始化為0。(3)添加一個(gè)新類,實(shí)現(xiàn)矩形的保存。方法是選擇Insert|New Class命令,彈出New Class對(duì)話框,如圖7.16所示。圖7.16 New Class對(duì)話框類的名稱為CPRetangle,為了實(shí)現(xiàn)串行化,其基類需要是CObject的子類,在此選擇CEdit類。單擊OK按鈕。(4)在CPRetangle添加數(shù)據(jù)成員,并修改其構(gòu)造函數(shù),具體代碼如下:CPRetangle(CPoint a=0,CPoint b=0);/默認(rèn)參數(shù)的構(gòu)造函數(shù)CPoint x;/添加變量CPoint y;上面是修改了構(gòu)造函數(shù),并且添加了兩個(gè)數(shù)據(jù)成員,保存矩形的坐標(biāo)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論