第6章 文檔與視圖_第1頁
第6章 文檔與視圖_第2頁
第6章 文檔與視圖_第3頁
第6章 文檔與視圖_第4頁
第6章 文檔與視圖_第5頁
已閱讀5頁,還剩60頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、l文檔與視圖結(jié)構(gòu)的工作原理l菜單編程l工具欄編程l狀態(tài)欄編程l文檔的讀寫操作機制第六章第六章 文檔與視圖文檔與視圖 一般說來,文檔文檔是能夠被邏輯地組合的一系列數(shù)據(jù),包括文本、圖形、圖象和表格數(shù)據(jù)。 一個文檔文檔代表了用戶存儲或打開的一個文件單位。6.1 文檔與視圖結(jié)構(gòu)文檔與視圖結(jié)構(gòu)6.1.1 文檔與視圖結(jié)構(gòu)文檔與視圖結(jié)構(gòu)概述概述 視圖視圖是文檔文檔在屏幕上的一個映像,它就像一個觀景器,用戶通過視圖看到文檔,也是通過視圖來改變文檔,視圖充當(dāng)了文檔與用戶之間的媒介物。 一個視圖視圖總是與一個文檔對象相關(guān)聯(lián),用戶通過與文檔相關(guān)聯(lián)的視圖與文檔進(jìn)行交互。當(dāng)用戶打開一個文檔時,應(yīng)用程序就會創(chuàng)建一個與之相

2、關(guān)聯(lián)的視圖。l視圖視圖負(fù)責(zé)顯示和編輯文檔數(shù)據(jù),但不負(fù)責(zé)存儲。用戶對數(shù)據(jù)的編輯需要依靠窗口上的鼠標(biāo)與鍵盤操作才得以完成,這些消息都是由視圖類接收后進(jìn)行處理或通知文檔類。l文檔文檔負(fù)責(zé)數(shù)據(jù)的讀寫操作,數(shù)據(jù)通常被保存在文檔類的成員變量中,文檔類通過一個稱為序列化的成員函數(shù)將成員變量的數(shù)據(jù)保存到磁盤文件中。MFC應(yīng)用程序為數(shù)據(jù)的序列化提供了默認(rèn)支持。 l 分為數(shù)據(jù)的管理和顯示l 文檔文檔用于管理和維護數(shù)據(jù)l 視圖視圖用來顯示和編輯數(shù)據(jù) MFC通過其文檔類和視圖類提供了大量有關(guān)數(shù)據(jù)處理的方法。l一個視圖視圖是一個沒有邊框的窗口,它位于主框架窗口中的客戶區(qū)。視圖是文檔文檔對外顯示的窗口,但它并不能完全獨立

3、,它必須依存在一個框架窗口框架窗口內(nèi)。l一個視圖只能擁有一個文檔,但一個文檔可以同時擁有多個視圖。視圖是文檔在屏幕上的一個映像,它就像一個觀景器1視圖類的成員函數(shù)GetDocument() 一個視圖對象只有一個與之相關(guān)聯(lián)的文檔對象。在MFC應(yīng)用程序中,視圖對象通過調(diào)用成員函數(shù)函數(shù)GetDocument()得到當(dāng)前文檔。GetDocument()是視圖類的成員函數(shù),調(diào)用它可以返回與視圖相關(guān)聯(lián)的文檔對象的指針,利用這個指針可以訪問文檔類及其派生類的公有成員。 6.1.2 文檔與視圖之間的相互作用文檔與視圖之間的相互作用 一個文檔對象可以有多個與之相關(guān)聯(lián)的視圖對象,當(dāng)一個文檔的數(shù)據(jù)通過某個視圖被修改

4、后,與它關(guān)聯(lián)的每一個視圖都必須反映出這些修改。因此,視圖在需要時必須進(jìn)行重繪,即當(dāng)文檔數(shù)據(jù)發(fā)生改變時,必須通知到所有相關(guān)聯(lián)的視圖對象,以便更新所顯示的數(shù)據(jù)。 更新與該文檔有關(guān)的所有視圖的方法是調(diào)用成員函數(shù)CDocument:UpdateAllViews()。 如 果 在 文 檔 派 生 類 的 成 員 函 數(shù) 中 調(diào) 用UpdateAllViews()函數(shù),其第一個參數(shù)pSender設(shè)為NULL,表示所有與當(dāng)前文檔相關(guān)的視圖都要重繪(參見例6-3)。 如果在視圖派生類的成員函數(shù)中通過當(dāng)前文檔指針調(diào)用UpdateAllViews()函數(shù),其第一個參數(shù)pSender設(shè)為當(dāng)前視圖,如下形式: Get

5、Document()-UpdateAllViews(this)函數(shù)聲明:函數(shù)聲明:void UpdateAllViews(CView* pSender, LPARAM lHint = 0L, CObject* pHint=NULL ); 當(dāng)程序調(diào)用CDocument:UpdateAllViews()函數(shù)時,實際上是調(diào)用了所有相關(guān)視圖的OnUpdate()函數(shù),以更新相關(guān)的視圖。需要時,可以直接在視圖派生類的成員函數(shù)中調(diào)用該函數(shù)刷新當(dāng)前視圖。3視圖類的成員函數(shù)OnUpdate()void CView:OnUpdate(CView* pSender, LPARAM /*lHint*/, CObje

6、ct* /*pHint*/)ASSERT(pSender != this);UNUSED(pSender); / unused in release builds/ invalidate the entire pane, erase background tooInvalidate(TRUE); / 使整個窗口矩形無效,通過調(diào) / 用OnDraw()更新整個視圖窗口基類CView的成員函數(shù) 在OnUpdate()中通過調(diào)用函數(shù)CWnd:Invalidate()刷新整個客戶區(qū),我們也可以在自己的CWnd派生類中直接調(diào)用函數(shù)Invalidate()??偨Y(jié)總結(jié):刷新視圖時默認(rèn)的函數(shù)調(diào)用過程: CDo

7、cument:UpdateAllViews() CView:OnUpdate() CWnd:Invalidate() OnPaint() OnDraw()MFC多文檔應(yīng)用程序與單文檔程序的根本差別:多文檔應(yīng)用程序與單文檔程序的根本差別:lSDI和MDI使用不同框架窗口。SDI的框架窗口是一的主框架窗口,窗口類是CMainFrame,由CFrameWnd派生而來。lMDI的框架窗口分為主框架窗口和子框架窗口,區(qū)別于SDI,MDI的主框架窗口不包含視圖,分別由每個子框架窗口包含一個視圖。MDI的主框架窗口類不與某個打開的文檔相關(guān)聯(lián),而只與子框架窗口相關(guān)聯(lián)。lMDI窗口類的派生關(guān)系如下:CMDIFr

8、ameWnd:CMainFrame主框架窗口類;CMDIChildWnd:CChildFrame子框架窗口類; l在文檔/視圖結(jié)構(gòu)中,數(shù)據(jù)以文檔類對象的形式存在。文檔對象通過視圖對象顯示,而視圖對象又是主框架窗口的一個子窗口,并且涉及文檔操作的菜單和工具欄等資源也是建立在主框架窗口上。l文檔、視圖、框架類和所涉及的資源形成了一種文檔、視圖、框架類和所涉及的資源形成了一種固定的聯(lián)系,這種固定的聯(lián)系就稱為文檔模板。固定的聯(lián)系,這種固定的聯(lián)系就稱為文檔模板。l換句話說文檔模板就是換句話說文檔模板就是描述了對應(yīng)于每一種類型描述了對應(yīng)于每一種類型文檔的視圖和窗口的類型,由其來確立文檔、視文檔的視圖和窗口

9、的類型,由其來確立文檔、視圖、框架和各種資源之間的固定關(guān)系。圖、框架和各種資源之間的固定關(guān)系。SDI和和MDI文檔模板的樣式:文檔模板的樣式:文檔模板是在文檔模板是在APP類的初始化函數(shù)類的初始化函數(shù)InitInstance()中聲明。中聲明。CSingleDocTemplate* pDocTemplate;pDocTemplate = new CSingleDocTemplate( /單文檔模板單文檔模板IDR_MAINFRAME, /主框架資源的主框架資源的IDRUNTIME_CLASS(CMySDIDoc), /SDI文檔類文檔類RUNTIME_CLASS(CMainFrame), /

10、SDI主框架窗口類主框架窗口類RUNTIME_CLASS(CMySDIView); /SDI視圖類視圖類AddDocTemplate(pDocTemplate);/CMultiDocTemplate* pDocTemplate;pDocTemplate = new CMultiDocTemplate(IDR_MYMDITYPE,/子框架窗口資源子框架窗口資源IDRUNTIME_CLASS(CMyMDIDoc),RUNTIME_CLASS(CChildFrame), / MDI子框架窗口類子框架窗口類RUNTIME_CLASS(CMyMDIView);AddDocTemplate(pDocTem

11、plate);1、建立菜單資源、建立菜單資源實例:創(chuàng)建一個名為DrawCoin的SDI項目,添加“畫硬幣”主菜單,并增加兩個菜單項“增加硬幣”、 “減少硬幣”。編程:(1)添加頂層菜單“畫硬幣(&C)”(2)增加兩個菜單項(Menu Item)ID_COIN_ADD 增加硬幣(&A)tCtrl+A 在客戶區(qū)增加一枚硬幣n增幣ID_COIN_SUB 減少硬幣(&S)tCtrl+S 在客戶區(qū)減少一枚硬幣n減幣2、添加菜單命令的處理函數(shù)、添加菜單命令的處理函數(shù)菜單實則一系列命令的列表,當(dāng)某一菜單項被點擊后,一個含有該菜單項ID標(biāo)識的WM_COMMAND命令消息將發(fā)送給APP窗

12、口,APP將該消息轉(zhuǎn)換為一個“命令消息處理函數(shù)”的函數(shù)調(diào)用,從而響應(yīng)命令。利用“類向?qū)А?Ctrl+W)工具為菜單添加消息映射函數(shù),并添加用戶代碼在OnCoinAdd()函數(shù)中添加在OnCoinSub()函數(shù)中添加m_nCoins+; /硬幣加一UpdateAllViews(NULL); /刷新視圖If(m_nCoins0)m_nCoins-; /硬幣減一UpdateAllViews(NULL); /刷新視圖本例中,為了實現(xiàn)菜單的操作功能,還必須完成如下三步:(1)為文檔類添加一個名為m_nCoins的公有型整型變量;(2)利用類向?qū)Чぞ邽槲臋n類添加名為“DeleteContents”的消息處

13、理函數(shù),并在其內(nèi)對m_nCoins=1初始化 。該函數(shù)在用戶重新使用一個文檔時自動調(diào)用。(3)修改視圖類的OnDraw()函數(shù),根據(jù)文檔類保存的m_nCoins當(dāng)前值畫出指定數(shù)量的硬幣for (int i=0;im_nCoins;i+)int y=200-10*i;pDC-Ellipse(200,y,300,y-30);pDC-Ellipse(200,y-10,300,y-35);/用兩個上下偏移橢圓表示硬幣UPDATE_COMMAND_UI是“更新用戶界面命令消息”:它能夠根據(jù)程序當(dāng)前運行狀態(tài)來動態(tài)設(shè)置菜單項的狀態(tài)(可用或不可用)。在程序剛運行時,將菜單項“減少硬幣” 置為“不可用”(灰顯狀

14、態(tài))。需要在其UPDATE_COMMAND_UI消息映射函數(shù)中,添加代碼:if (m_nCoinsEnable(FALSE);/禁用菜單項(灰顯)elsepCmdUI-Enable(TRUE);/使能菜單項(正常顯示)3、為菜單命令設(shè)置加速鍵、為菜單命令設(shè)置加速鍵在資源視圖Accelerator中IDR_MAINFRAME項的加速鍵列表最后一空行操作。4、為新菜單添加、為新菜單添加“彈出式快捷菜單彈出式快捷菜單”利用類向?qū)橐晥D類添加WM_CONTEXTMENU消息處理函數(shù),并添加如下代碼:CMenu menuPopup;/聲明菜單對象if (menuPopup.CreatePopupMenu

15、()/創(chuàng)建菜單menuPopup.AppendMenu(MF_STRING,ID_COIN_ADD,”增加硬幣tCtrl+A”); /向菜單中添加菜單項menuPopup.AppendMenu(MF_STRING,ID_COIN_SUB,”減少硬幣tCtrl+M”);/向菜單中添加菜單項/顯示彈出式菜單,并對用戶選擇做出響應(yīng)menuPopup.TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);6.4 工具欄和狀態(tài)欄設(shè)計工具欄和狀態(tài)欄設(shè)計6.4.1 添加工具欄按鈕添加工具欄按鈕 我們知道單擊工具欄按鈕也產(chǎn)生命令消息。而且,事實上工具欄按鈕和菜單

16、項的功能往往是一致的。為了使工具欄上某個按鈕的功能與某個菜單命令的功能相同,只需讓該按鈕的ID值與對應(yīng)菜單命令的ID值相同即可。例例6-10 工具欄編程工具欄編程 狀態(tài)欄狀態(tài)欄用于顯示當(dāng)前操作的提示信息和程序的運行狀態(tài)。 MFC應(yīng)用程序默認(rèn)的狀態(tài)欄分為四個部分:l 第1部分:顯示菜單或工具欄的提示信息l 第2部分: Caps Lock,顯示鍵盤的大小寫狀態(tài)l 第3部分: Num Lock,顯示鍵盤的數(shù)字狀態(tài)l 第4部分: Scroll Lock,顯示鍵盤的滾動狀態(tài) 狀態(tài)欄上的每個部分稱為一個面板(pane)。 static UINT indicators =ID_SEPARATOR, / 定義

17、分隔符,作為提示信息行的面板標(biāo)識ID_INDICATOR_CAPS, / 大寫指示器面板標(biāo)識ID_INDICATOR_NUM, / 數(shù)字指示器面板標(biāo)識ID_INDICATOR_SCRL, / 滾動指示器面板標(biāo)識; 利用MFC AppWizard向?qū)?chuàng)建應(yīng)用程序時,在C M a i n F r a m e 類 中 定 義 了 一 個 成 員 變 量m_wndStatusBar,它是狀態(tài)欄CStatusBar類的對象。 在MFC應(yīng)用程序框架的實現(xiàn)文件MainFrm.cpp中,為狀態(tài)欄定義了一個靜態(tài)數(shù)組indicators。 為 了 顯 示 硬 幣 數(shù) 量 , 添 加 一 個 I D 為ID_IND

18、ICATOR_COIN的指示器面板,將數(shù)組indicators作如下修改:static UINT indicators =ID_SEPARATOR, / status line indicatorID_INDICATOR_COIN, / 顯示硬幣數(shù)量指示器顯示硬幣數(shù)量指示器ID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL,; 修改OnDraw()函數(shù),添加顯示硬幣數(shù)量的代碼: . . . . . . CString strCoins;/ 先獲得主窗口,先獲得主窗口, 再獲得狀態(tài)欄的指針再獲得狀態(tài)欄的指針CStatusBar* pStatu

19、s=(CStatusBar*)AfxGetApp()-m_pMainWnd-GetDescendantWindow(ID_VIEW_STATUS_BAR); if(pStatus)strCoins.Format(硬幣硬幣:%d, pDoc-m_nCoins); / 設(shè)置要顯示的信息設(shè)置要顯示的信息pStatus-SetPaneText(1, strCoins); / 顯示硬幣數(shù)量,面板編號從顯示硬幣數(shù)量,面板編號從0開始開始 . . . . . .lWindows是基于事件驅(qū)動、消息傳遞的操作系統(tǒng)。用戶所有的輸入都是以事件或消息的形式傳遞給應(yīng)用程序的,鼠標(biāo)也不例外。l鼠標(biāo)驅(qū)動程序?qū)⑹髽?biāo)硬件信號

20、轉(zhuǎn)換成Windows可以識別的信息,Windows根據(jù)這些信息構(gòu)造鼠標(biāo)消息,并將它們發(fā)送到應(yīng)用程序的消息隊列中。鼠標(biāo)操作:單擊、雙擊、釋放和移動 主要鼠標(biāo)消息主要鼠標(biāo)消息:l WM_MOUSEMOVE:移動l WM_LBUTTONDOWN:按下左鍵l WM_LBUTTONUP:釋放左鍵l WM_RBUTTONDOWN:按下右鍵l WM_RBUTTONUP:釋放右鍵l WM_LBUTTONDBLCLK:雙擊左鍵 l 客戶區(qū)鼠標(biāo)消息l 非客戶區(qū)鼠標(biāo)消息: WM_NCLBUTTONDOWN:按下鼠標(biāo)左鍵消 WM_NCRBUTTONDOWN:按下鼠標(biāo)右鍵 . . . . . . 非客戶區(qū)鼠標(biāo)消息由Wi

21、ndows操作系統(tǒng)處理,應(yīng)用程序一般不需要處理??蛻魠^(qū)鼠標(biāo)消息發(fā)送到應(yīng)用程序后,可以由應(yīng)用程序自己處理。 利用MFC ClassWizard類向?qū)傻氖髽?biāo)消息處理函數(shù)一般都有兩個參數(shù): nFlags:類型為UINT,表示鼠標(biāo)按鍵和 鍵盤上控制鍵的狀態(tài)。 point:類型為CPoint,表示鼠標(biāo)當(dāng)前所 在位置坐標(biāo)。 使用鼠標(biāo)的一個典型例子就是繪圖程序,鼠標(biāo)被用作畫筆,繪圖過程中要進(jìn)行不同鼠標(biāo)消息的處理,如按下鼠標(biāo)、釋放鼠標(biāo)和移動鼠標(biāo)等。當(dāng)用戶按下鼠標(biāo)左鍵時必須記錄下當(dāng)前鼠標(biāo)的位置,當(dāng)用戶移動鼠標(biāo)時,如果鼠標(biāo)左鍵被按住,則從上一個鼠標(biāo)位置到當(dāng)前位置畫一段直線,并保存當(dāng)前鼠標(biāo)的位置,供下一次畫線用

22、。當(dāng)用戶彈起鼠標(biāo)左鍵時釋放鼠標(biāo)。 例例 編寫一個繪圖程序,程序運行后,當(dāng)用戶在客戶區(qū)窗口按下鼠標(biāo)左鍵并移動時,根據(jù)鼠標(biāo)移動的軌跡繪制出指定的線段。 1利用MFC AppWizardexe向?qū)?chuàng)建一個SDI應(yīng)用程序MyDraw,為視圖類CMyDrawView添加成員變量: protected: / 定義有關(guān)鼠標(biāo)作圖的成員變量CPoint m_ptOrigin; / 起始點坐標(biāo)起始點坐標(biāo)bool m_bDragging; / 拖拽標(biāo)記拖拽標(biāo)記HCURSOR m_hCross; / 光標(biāo)句柄光標(biāo)句柄 2在視圖類CMyDrawView構(gòu)造函數(shù)中設(shè)置拖拽標(biāo)記和十字光標(biāo)。CMyDrawView:CMyDr

23、awView()/ TODO: add construction code herem_bDragging=false; / 初始化拖拽標(biāo)記初始化拖拽標(biāo)記/ 獲得十字光標(biāo)句柄m_hCross=AfxGetApp()- LoadStandardCursor(IDC_CROSS); 3利用ClassWizard類向?qū)橐晥D類添加按下鼠標(biāo)左鍵WM_LBUTTONDOWN的消息處理函數(shù)。void CMyDrawView:OnLButtonDown(UINT nFlags, CPoint point) / TODO: Add your message . . . . . .SetCapture(); /

24、 捕捉鼠標(biāo)捕捉鼠標(biāo):SetCursor(m_hCross); / 設(shè)置十字光標(biāo)設(shè)置十字光標(biāo)m_ptOrigin=point;m_bDragging=TRUE; / 設(shè)置拖拽標(biāo)記設(shè)置拖拽標(biāo)記/ CView:OnLButtonDown(nFlags, point); 利用ClassWizard類向?qū)橐晥D類添加鼠標(biāo)移動WM_MOUSEMOVE的消息處理函數(shù)。void CMyDrawView:OnMouseMove(UINT nFlags, CPoint point) / TODO: Add your message . . . . . . if(m_bDragging)CClientDC dc(t

25、his);dc.MoveTo(m_ptOrigin); dc.LineTo(point); / 繪制線段繪制線段m_ptOrigin=point; / 新的起始點新的起始點/ CView:OnMouseMove(nFlags, point);void CMyDrawView:OnLButtonUp(UINT nFlags, CPoint point) / TODO: Add your message . . . . . . if(m_bDragging) m_bDragging=false; / 清拖拽標(biāo)記清拖拽標(biāo)記 ReleaseCapture(); / 釋放鼠標(biāo),還原鼠標(biāo)形狀釋放鼠標(biāo),還原

26、鼠標(biāo)形狀/ CView:OnLButtonUp(nFlags, point); 系統(tǒng)中任一時刻只有當(dāng)前窗口才能捕獲鼠標(biāo)。在程序中需要時通過調(diào)用函數(shù)CWnd:SetCapture()捕獲鼠標(biāo),使用鼠標(biāo)畫圖結(jié)束后應(yīng)該調(diào)用函數(shù)ReleaseCapture()釋放鼠標(biāo)。 利用ClassWizard類向?qū)橐晥D類添加左鍵釋放WM_LBUTTONUP的消息處理函數(shù)。 MyDraw程序有一個缺陷,當(dāng)改變窗口大小或?qū)⒋翱谧钚』笤僦匦麓蜷_,原來的線段沒有顯示出來。其原因是此時調(diào)用的是視圖類的刷新函數(shù)OnDraw(),而在該函數(shù)中并沒有實現(xiàn)繪制線段的功能。 完善繪圖程序MyDraw 1 為 線 段 定 義 新

27、類 C L i n e 。 選 擇“Insert|New Class”菜單命令,彈出New Class對話框中,在Class type欄選擇Generic Class,在類名Name欄輸入CLine,在類名Base classes欄輸入CObject,單擊OK按鈕,自動生成了類CLine的頭文件Line.h和實現(xiàn)文件Line.cpp的框架。例例 完善繪圖程序MyDraw,在重繪窗口時能夠顯示已繪制的線段。 2為類CLine定義成員變量和成員函數(shù)。class Cline : CObjectprivate:/ 定義成員變量,表示一條直線起點和終點的坐標(biāo)定義成員變量,表示一條直線起點和終點的坐標(biāo)CP

28、oint m_pt1;CPoint m_pt2;public:CLine();virtual CLine();CLine(CPoint pt1, CPoint pt2); / 構(gòu)造函數(shù)構(gòu)造函數(shù)void DrawLine(CDC *pDC); / 繪制線段繪制線段;CLine:CLine(CPoint pt1, CPoint pt2)m_pt1=pt1;m_pt2=pt2;void CLine:DrawLine(CDC* pDC)pDC-MoveTo(m_pt1);pDC-LineTo(m_pt2); 3一般都使用數(shù)組來保存多條線段的數(shù)據(jù),而且MFC提供了實現(xiàn)動態(tài)數(shù)組的類模板。類CObArray

29、支持CObject指針數(shù)組,用它定義的對象可以動態(tài)生成。這樣,可將存放每條線段數(shù)據(jù)的變量的指針存到CObArray類的對象中。為此在文檔類CMyDrawDoc中定義有關(guān)的成員變量和成員函數(shù),需要包含CLine類定義的頭文件。 #include Line.h#include / 使用使用MFC類模板類模板class CMyDrawDoc : public CDocument . . . . . .protected:CTypedPtrArray m_LineArray; / 存放線段對象指針的動態(tài)數(shù)組存放線段對象指針的動態(tài)數(shù)組public:CLine* GetLine(int nIndex);

30、/ 獲取指定序號線段對象的指針獲取指定序號線段對象的指針void AddLine(CPoint pt1, CPoint pt2); / 向動態(tài)數(shù)組中添加新的線段對象的指針向動態(tài)數(shù)組中添加新的線段對象的指針int GetNumLines(); / 獲取線段的數(shù)量獲取線段的數(shù)量. . . . . .; 成員變量m_LineArray是類模板CTypedPtrArray的對象。使用數(shù)組類模板CTypedPtrArray需要指定兩個模板參數(shù): CTypedPtrArray 參 數(shù) B A S E _ C L A S S 指 定 基 類 , 可 以 是CObArray或CPtrArray;參數(shù)TYPE指

31、定存儲在基類數(shù)組中元素的類型。本例中,這兩個參數(shù)分別為CObArray和CLine*,表示m_LineArray是CObArray的派生類對象,用來存放CLine對象的指針。 為 了 使 用 M F C 類 模 板 , 須 包 含 頭 文 件afxtempl.h。 其他主要成員函數(shù)成員函數(shù):void CMyDrawDoc:AddLine(CPoint pt1, CPoint pt2)CLine* pLine=new CLine(pt1, pt2); / 新建一條線段對象m_LineArray.Add(pLine); / 將該線段加到動態(tài)數(shù)組CLine* CMyDrawDoc:GetLine(i

32、nt nIndex)if(nIndexm_LineArray.GetUpperBound() / 判斷是否越界return NULL;return m_LineArray.GetAt(nIndex); / 返回給定序號線段對象的指針int CMyDrawDoc:GetNumLines()return m_LineArray.GetSize(); / 返回線段的數(shù)量 4當(dāng)鼠標(biāo)移動時,除了繪制線段,還要保存當(dāng)前線段的起點坐標(biāo)和終點坐標(biāo)。需要在視圖類CMyDrawView的OnMouseMove()鼠標(biāo)移動消息處理函數(shù)中添加有關(guān)代碼。void CMyDrawView:OnMouseMove(UINT

33、 nFlags, CPoint point) / TODO: Add your message handler code here and/or call defaultif(m_bDragging)CMyDrawDoc *pDoc=GetDocument(); /獲得文檔對象指針ASSERT_VALID(pDoc); /測試文檔對象是否運行有效pDoc-AddLine(m_ptOrigin, point); /加入線段到指針數(shù)組CClientDC dc(this);dc.MoveTo(m_ptOrigin); dc.LineTo(point); / 繪制線段m_ptOrigin=point;

34、 / 新的起始點/ CView:OnMouseMove(nFlags, point); 為了在改變程序窗口大小或最小化窗口后重新打開窗口時保留窗口中原有的圖形,必須在OnDraw()函數(shù)中重新繪制前面利用鼠標(biāo)所繪制的線段。這些線段的坐標(biāo)作為類CLine對象的成員變量,所有CLine對象的指針已保存在動態(tài)數(shù)組m_LineArray中。 void CMyDrawView:OnDraw(CDC* pDC)CMyDrawDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data hereint n

35、Index=pDoc-GetNumLines(); / 取得線段的數(shù)量/ 循環(huán)畫出每一段線段while(nIndex-) / 數(shù)組下標(biāo)從0到nIndex-1pDoc-GetLine(nIndex)-DrawLine(pDC); / 類CLine的成員函數(shù) 涉及到數(shù)據(jù)處理的應(yīng)用程序一般都要考慮文檔數(shù)據(jù)的永久保存: 1、C+文件流 2、Cfile類 3、 CAchive 類:在MFC應(yīng)用程序中,序列化序列化(Serialize)使得程序員可以不直接面對一個物理文件而進(jìn)行文檔的讀寫。序列化實現(xiàn)了文檔數(shù)據(jù)的保存和裝入的幕后工作,MFC通過序列化實現(xiàn)應(yīng)用程序的文檔讀寫功能。 :在MFC中,CFile類專

36、門用于處理文件,使用它,需要在程序中包含afx.h的頭文件,而且還需要對工程進(jìn)行特定設(shè)置,即Project | SettingsLink標(biāo)簽頁MFC項Use MFC in a Dll or Static Library。使用該類的缺點在于打開或讀寫文件時可能發(fā)生異常情況,需要進(jìn)行復(fù)雜的異常處理。1. 序列化的基本思想:序列化的基本思想: 對象可以將其當(dāng)前狀態(tài)(由其成員變量的值表示)寫入永久性存儲體(通常是指磁盤)中,以后可以從永久性存儲體中讀?。ㄝd入)對象的狀態(tài),從而重建對象。類的對象自己應(yīng)該具備將狀態(tài)值寫入磁盤或從磁盤中讀出的方法(即成員函數(shù)),這種對象的保存和恢復(fù)的過程稱為序列化序列化。

37、一個可序列化的類必須有一個稱作為序列化的成員函數(shù)Serialize(),文檔的序列化在文檔類的成員函數(shù)Serialize()中進(jìn)行。MFC AppWizard應(yīng)用程序向?qū)г谏蓱?yīng)用程序時只創(chuàng)建了文檔派生類序列化Serialize()函數(shù)的框架,由于不同程序的數(shù)據(jù)結(jié)構(gòu)各不相同,可序列化的類應(yīng)該重載Serialize()函數(shù),使其支持對特定數(shù)據(jù)的序列化。并且,任何需要保存的變量(數(shù)據(jù))都應(yīng)該在文檔派生類中聲明。 void CMyDoc:Serialize(CArchive& ar) if(ar.IsStoring()/ TODO:add storing code here.else/ TO

38、DO:add loading code here. 函數(shù)參數(shù)ar是一個CArchive類的對象,文檔數(shù)據(jù)的序列化操作通過CArchive類對象作為中介來完成。CArchive類對象由應(yīng)用程序框架創(chuàng)建,并與用戶正在使用的文件關(guān)聯(lián)在一起。CArchive類包含一個類CFile指針的成員變量,當(dāng)創(chuàng)建一個CArchive類對象時,該對象與一個類CFile或其派生類的對象聯(lián)系在一起,代表一個已打開的文件。 C+主要通過文件句柄來實現(xiàn)磁盤輸入和輸出,一個文件句柄與一個磁盤文件相關(guān)聯(lián)。而MFC中物理文件的讀寫操作是由CFile類及其派生類來完成的,它們對文件句柄進(jìn)行了封裝。CArchive類對象為讀寫CFi

39、le類對象中的可序列化數(shù)據(jù)提供了一種安全的緩沖機制,它們之間形成了如下關(guān)系: Serialize()函數(shù) CArchive類對象CFile類對象 磁盤文件 1. CDocument:OnFileSave()完成的工作:完成的工作:l文檔對象獲取一個當(dāng)前文件CFile指針,創(chuàng)建一個CArchive對象;l文檔對象調(diào)用成員函數(shù)Serialize(),并把創(chuàng)建的CArchive對象作為參數(shù)傳遞給函數(shù)Serialize();lSerialize()函數(shù)根據(jù)函數(shù)IsStoring()的返回值(true)執(zhí)行if語句的第一個分支,調(diào)用要讀寫對象的序列化函數(shù)Serialize(),而讀寫對象使用CFile來

40、寫入數(shù)據(jù)。 l類必須直接或間接地從CObject類派生而來,因為是利用CArchive類把用戶的CObject類的派生類對象序列化;l類必須定義一個不帶參數(shù)的構(gòu)造函數(shù),當(dāng)從磁盤文件載入文檔時調(diào)用該構(gòu)造函數(shù)來創(chuàng)建一個可序列化的對象,使用從文件中讀出來的數(shù)據(jù)填充對象的成員變量;l在類的頭文件中使用DECLARE_SERIAL宏,在類的實現(xiàn)文件中使用IMPLEMENT_SERIAL宏;l在自定義類中重載序列化成員函數(shù)Serialize()。 1. 前面已定義了用來保存線段數(shù)據(jù)的CLine類,它已是CObject的派生類,現(xiàn)在添加函數(shù)Serialize()的聲明和DECLARE_SERIAL宏。2. 在實現(xiàn)源文件Line.cpp中成員函數(shù)定義前添加IMPLEMENT_SERIAL宏: IMPLEMENT_SERIAL(CLine, CObject, 1) / 實現(xiàn)序列化類Cline3. 編寫類CLine的序列化函數(shù)Serialize()。 void CLine:Serialize(CArchive &ar) if(ar.IsStoring()arm_pt1m_pt1m_pt2; / 讀出對象的數(shù)據(jù)4現(xiàn)在我們實現(xiàn)了CLine類的序列化,但只是一條線段的序列化。前面

溫馨提示

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

評論

0/150

提交評論