第6章數(shù)據(jù)和文檔.ppt_第1頁(yè)
第6章數(shù)據(jù)和文檔.ppt_第2頁(yè)
第6章數(shù)據(jù)和文檔.ppt_第3頁(yè)
第6章數(shù)據(jù)和文檔.ppt_第4頁(yè)
第6章數(shù)據(jù)和文檔.ppt_第5頁(yè)
已閱讀5頁(yè),還剩41頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、第6章數(shù)據(jù)和文檔,6.1CString類(lèi),6.2使用簡(jiǎn)單數(shù)組集合類(lèi),6.3使用CFile類(lèi),6.4文檔序列化,6.5綜合應(yīng)用,6.1CString類(lèi),6.1.1 BSTR、const char*、LPCTSTR和CString 什么是BSTR、LPSTR以及LPWSTR呢? BSTR(Basic STRing,Basic字符串)是一個(gè)OLE CHAR*類(lèi)型的Unicode字符串。它被描述成一個(gè)與自動(dòng)化相兼容的類(lèi)型。由于操作系統(tǒng)提供相應(yīng)的API函數(shù)(如SysAllocString)來(lái)管理它以及一些默認(rèn)的調(diào)度代碼,因此BSTR實(shí)際上就是一個(gè)COM字符串,但它卻在自動(dòng)化技術(shù)以外的多種場(chǎng)合下也得到了較

2、為廣泛的使用。 LPSTR和LPWSTR是Win32和Visual C+所使用的一種字符串?dāng)?shù)據(jù)類(lèi)型。LPSTR被定義成是一個(gè)指向以NULL(0)結(jié)尾的8位ANSI字符數(shù)組指針,而LPWSTR是一個(gè)指向以NULL結(jié)尾的16位雙字節(jié)字符數(shù)組指針。在Visual C+中,還有類(lèi)似的字符串類(lèi)型,如LPTSTR、LPCTSTR等,它們的含義如圖6.1所示。,圖6.1 字符串類(lèi)型表示的含義,6.1CString類(lèi),例如,LPCTSTR是指“l(fā)ong pointer to a constant generic string”,表示“一個(gè)指向一般字符串常量的長(zhǎng)指針類(lèi)型”,與C/C+的const char*相映

3、射,而LPTSTR映射為 char*。 一般地,Visual C+中還有下列類(lèi)型定義: #ifdef UNICODE typedef LPWSTR LPTSTR; typedef LPCWSTR LPCTSTR; #else typedefLPSTR LPTSTR; typedef LPCSTR LPCTSTR; #endif,6.1CString類(lèi),CString類(lèi)支持字符串類(lèi)型,并可通過(guò)CString類(lèi)構(gòu)造函數(shù)和一些運(yùn)算符進(jìn)行構(gòu)造。CString類(lèi)構(gòu)造函數(shù)原型如下: CString( ); CString( const CString / 從C語(yǔ)言樣式的字符串來(lái)創(chuàng)建city,6.1CStr

4、ing類(lèi),當(dāng)然,也可使用CString類(lèi)的Format成員函數(shù)將任意數(shù)據(jù)類(lèi)型轉(zhuǎn)換成CString字符串。Format成員函數(shù)使用C語(yǔ)言的printf的格式樣式進(jìn)行創(chuàng)建,例如: CString str; str.Format( Floating point: %.2fn, 12345.12345); str.Format( Left-justified integer: %.6dn, 35); 若將一個(gè)CString字符串向上述字符串類(lèi)型進(jìn)行轉(zhuǎn)換,則可使用CString類(lèi)提供了的const char*、LPCTSTR運(yùn)算符以及AllocSysString和SetSysString成員函數(shù)等。例如

5、: / 將CString向LPTSTR轉(zhuǎn)換的方法一 CString theString( This is a test ); LPTSTR lpsz = new TCHARtheString.GetLength()+1; / TCHAR在Unicode平臺(tái)中等同于WCHAR(16位Unicode字符),在ANSI中等價(jià)于char。 _tcscpy( lpsz, theString); / 將CString向LPTSTR轉(zhuǎn)換的方法二 CString theString( This is a test ); LPTSTR lpsz = (LPTSTR)(LPCTSTR)theString; / 將

6、CString向BSTR轉(zhuǎn)換 CString str(This is a test); BSTR bstrText = str.AllocSysString(); SysFreeString(bstrText); / 用完釋放,6.1CString類(lèi),6.1.2 字符串的字符訪問(wèn) 在CString類(lèi)中,可以用SetAt和GetAt來(lái)設(shè)置或獲取指定字符串中的字符,也可以使用運(yùn)算符“ ”來(lái)直接操作。它們的函數(shù)原型描述如下: void SetAt( int nIndex, TCHAR ch ); 其中,參數(shù)nIndex用來(lái)指CString對(duì)象中的某個(gè)字符的索引(從零開(kāi)始),它的值必須大于或等于0,且

7、應(yīng)小于由GetLength的返回的值。ch用來(lái)指定要插入的字符。這樣,就可將一個(gè)CString對(duì)象看作是一個(gè)字符數(shù)組,SetAt成員函數(shù)用來(lái)改寫(xiě)指定索引的字符。 TCHAR GetAt( int nIndex ) const; 該函數(shù)用來(lái)返回由nIndex指定索引位置(從零開(kāi)始)的TCHAR字符。例如: CString str( abcdef ); ASSERT( str.GetAt(2) = c ); / 斷言返回的字符與c相等。在MFC中,斷言機(jī)制常用于調(diào)試,當(dāng)斷言失敗后,程序在此中斷, / 然后彈出對(duì)話框,詢問(wèn)是否進(jìn)入調(diào)試或選擇其他操作 TCHAR operator ( int nInd

8、ex ) const; 這是一個(gè)運(yùn)算符重載函數(shù),即將一個(gè)CString對(duì)象看作是一個(gè)字符數(shù)組,使用下標(biāo)運(yùn)行符“”,通過(guò)指定下標(biāo)值nIndex來(lái)獲取相應(yīng)的字符。例如: CString str( abc ); ASSERT( str1 = b );,6.1CString類(lèi),6.1.3 清空及字符串長(zhǎng)度 清空CString對(duì)象可用Empty函數(shù),判斷CString對(duì)象是否為空用函數(shù)IsEmpty,獲取CString對(duì)象的字符串長(zhǎng)度用函數(shù)GetLength,它們的原型如下: void Empty( ); 該函數(shù)強(qiáng)迫CString對(duì)象為空(字符串長(zhǎng)度為0)并釋放相應(yīng)的內(nèi)存。 BOOL IsEmpty(

9、) const; 該函數(shù)用來(lái)判斷CString對(duì)象是否為空(字符串長(zhǎng)度為0),“是”為T(mén)RUE,“否”為FALSE。 int GetLength( ) const; 該函數(shù)用來(lái)獲取CString對(duì)象的字符串長(zhǎng)度(字符個(gè)數(shù)),這個(gè)長(zhǎng)度不包括字符串結(jié)尾的結(jié)束符。例如: CString s( abcdef ); ASSERT( s.GetLength() = 6 ); 6.1.4 提取和大小寫(xiě)轉(zhuǎn)換 CString類(lèi)提供許多用來(lái)從一個(gè)字符串中提取部分字符串的操作函數(shù),也提供了大小寫(xiě)轉(zhuǎn)換函數(shù)。下面分別說(shuō)明。 CString Left( int nCount ) const; 該函數(shù)用來(lái)從CString對(duì)

10、象中提取最前面的nCount個(gè)字符作為要提取的子字符串(簡(jiǎn)稱(chēng)子串)。如果nCount超過(guò)了字符串的長(zhǎng)度,則整個(gè)字符串都被抽取。 CString Mid( int nFirst ) const; CString Mid( int nFirst, int nCount ) const;,6.1CString類(lèi),該函數(shù)函數(shù)用從CString對(duì)象中提取一個(gè)從nFirst(從零開(kāi)始的索引)指定的位置開(kāi)始的nCount個(gè)字符的子串。若nCount不指定,則提取的子串是從nFirst開(kāi)始直到字符串結(jié)束。 CString Right( int nCount ) const; 該函數(shù)用來(lái)從CString對(duì)象中提

11、取最后面的nCount個(gè)字符作為要提取的子字符串。如果nCount超過(guò)了字符串的長(zhǎng)度,則整個(gè)字符串都被抽取。 void MakeLower( ); 該函數(shù)用來(lái)將CString對(duì)象的所有字符轉(zhuǎn)換成小寫(xiě)字符。 void MakeUpper( ); 該函數(shù)用來(lái)將CString對(duì)象的所有字符轉(zhuǎn)換成大寫(xiě)字符。 void TrimLeft( ); void CString:TrimLeft( TCHAR chTarget ); void CString:TrimLeft( LPCTSTR lpszTargets ); 該函數(shù)用來(lái)將CString對(duì)象最左邊的空格、空格和tab字符或chTarget指定的字符

12、或lpszTargets指定的子串刪除。 void TrimRight( ); void CString:TrimRight( TCHAR chTarget ); void CString:TrimRight( LPCTSTR lpszTargets );,6.1CString類(lèi),該函數(shù)用來(lái)將CString對(duì)象最后邊的空格、空格和tab字符或chTarget指定的字符或lpszTargets指定的子串刪除。 例如: CString strBefore; CString strAfter; strBefore = Hockey is Best! ; strAfter = strBefore; s

13、trAfter.TrimRight(! ); / strAfter中的字符串“Hockey is Best!”變成了“Hockey is Best” strBefore =Hockey is Best?!?!?!?! ; strAfter = strBefore; strAfter.TrimRight(?!?); / strAfter中的字符串“Hockey is Best?!?!?!?!”變成了“Hockey is Best”,6.2使用簡(jiǎn)單數(shù)組集合類(lèi),1. 簡(jiǎn)單數(shù)組集合類(lèi)的構(gòu)造及元素的添加 對(duì)簡(jiǎn)單數(shù)組集合類(lèi)構(gòu)造的方法都是一樣的,均是使用各自的構(gòu)造函數(shù),它們的原型如下: CByteArray

14、 CByteArray( ); CDWordArray CDWordArray( ); CObArray CObArray( ); CPtrArray CPtrArray( ); CStringArray CStringArray( ); CUIntArray CUIntArray( ); CWordArray CWordArray( ); 下面的代碼說(shuō)明了簡(jiǎn)單數(shù)組集合類(lèi)的兩種構(gòu)造方法: CObArray array; / 使用默認(rèn)的內(nèi)存塊大小 CObArray* pArray = new CObArray; / 使用堆內(nèi)存中的默認(rèn)的內(nèi)存塊大小 為了有效使用內(nèi)存,在使用簡(jiǎn)單數(shù)組集合類(lèi)之前最好調(diào)

15、用成員函數(shù)SetSize 設(shè)置此數(shù)組的大小,與其對(duì)應(yīng)的函數(shù)是GetSize,用來(lái)返回?cái)?shù)組的大小。它們的原型如下: void SetSize( int nNewSize, int nGrowBy = -1 ); int GetSize( ) const;,6.2使用簡(jiǎn)單數(shù)組集合類(lèi),其中,參數(shù)nNewSize用來(lái)指定新的元素的數(shù)目(必須大小或等于0)。nGrowBy表示當(dāng)數(shù)組需要擴(kuò)展時(shí)允許可添加的最少元素?cái)?shù)目,默認(rèn)時(shí)為自動(dòng)擴(kuò)展。 向簡(jiǎn)單數(shù)組集合類(lèi)添加一個(gè)元素,可使用成員函數(shù)Add和Append,它們的原型如下: int Add( CObject* newElement ); int Append(

16、 const CObArray 其中,Add函數(shù)是向數(shù)組的末尾添加一個(gè)新元素,且數(shù)組自動(dòng)增1。如果調(diào)用的函數(shù)SetSize的參數(shù)nGrowBy 的值大于1,那么擴(kuò)展內(nèi)存將被分配。此函數(shù)返回被添加的元素序號(hào),元素序號(hào)就是數(shù)組下標(biāo)。參數(shù)newElement表示要添加的相應(yīng)類(lèi)型的數(shù)據(jù)元素。而Append函數(shù)是向數(shù)組的末尾添加由src指定的另一個(gè)數(shù)組的內(nèi)容。函數(shù)返回加入的第一個(gè)元素的序號(hào)。,6.2使用簡(jiǎn)單數(shù)組集合類(lèi),2. 訪問(wèn)簡(jiǎn)單數(shù)組集合類(lèi)的元素 在MFC中,一個(gè)簡(jiǎn)單數(shù)組集合類(lèi)元素的訪問(wèn)既可以使用GetAt函數(shù),也可使用“”操作符,例如: / CObArray:operator 示例 CObArray

17、 array; CAge* pa;/ CAge是一個(gè)用戶類(lèi) array.Add( new CAge( 21 ) ); / 添加一個(gè)元素 array.Add( new CAge( 40 ) ); / 再添加一個(gè)元素 pa = (CAge*)array0; / 獲取元素0 array0 = new CAge( 30 ); / 替換元素0; / CObArray:GetAt示例 CObArray array; array.Add( new CAge( 21 ) ); / 元素 0 array.Add( new CAge( 40 ) ); / 元素 1,6.2使用簡(jiǎn)單數(shù)組集合類(lèi),3. 刪除簡(jiǎn)單數(shù)組集合

18、類(lèi)的元素 刪除簡(jiǎn)單數(shù)組集合類(lèi)中的元素一般需要進(jìn)行以下幾個(gè)步驟: (1)使用函數(shù)GetSize和整數(shù)下標(biāo)值訪問(wèn)簡(jiǎn)單數(shù)組集合類(lèi)中的元素。 (2)若對(duì)象元素是在堆內(nèi)存中創(chuàng)建的,則使用delete操作符刪除每一個(gè)對(duì)象元素。 (3)調(diào)用函數(shù)RemoveAll刪除簡(jiǎn)單數(shù)組集合類(lèi)中的所有元素。 例如,下面代碼是一個(gè)CObArray的刪除示例: CObArray array; CAge* pa1; CAge* pa2; array.Add( pa1 = new CAge( 21 ) ); array.Add( pa2 = new CAge( 40 ) ); ASSERT( array.GetSize() =

19、2 ); for (int i=0;iarray.GetSize();i+) delete array.GetAt(i); array.RemoveAll(); 需要說(shuō)明的是:函數(shù)RemoveAll是刪除數(shù)組中的所有元素,而函數(shù)RemoveAt( int nIndex, int nCount = 1)則表示要?jiǎng)h除數(shù)組中從序號(hào)為nIndex元素開(kāi)始的,數(shù)目為nCount的元素。,6.3使用CFile類(lèi),6.3.1 文件的打開(kāi)和關(guān)閉 在MFC中,使用CFile打開(kāi)一個(gè)文件通常使用下列兩個(gè)步驟: 構(gòu)造一個(gè)不帶任何參數(shù)的CFile對(duì)象; (1)調(diào)用成員函數(shù)Open并指定文件路徑以及文件標(biāo)志。 (2)C

20、File類(lèi)的Open函數(shù)原型如下: BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL ); 其中,lpszFileName用來(lái)指定一個(gè)要打開(kāi)的文件路徑,該路徑可以是相對(duì)的、絕對(duì)的或是一個(gè)網(wǎng)絡(luò)文件名(UNC)。nOpenFlags用來(lái)指定文件打開(kāi)的標(biāo)志,它的值見(jiàn)表6.1。pError用來(lái)表示操作失敗產(chǎn)生的CFileException指針,CFileException是一個(gè)與文件操作有關(guān)的異常處理類(lèi)。函數(shù)Open操作成功時(shí)返回TRUE,否則為FALSE。,6.3使用CFile類(lèi),表6.1

21、CFile類(lèi)的文件訪問(wèn)方式,6.3使用CFile類(lèi),例如,下面的代碼將顯示如何用讀寫(xiě)方式創(chuàng)建一個(gè)新文件: char* pszFileName = c:testmyfile.dat; CFile myFile; CFileException fileException; if ( !myFile.Open( pszFileName, CFile:modeCreate | CFile:modeReadWrite ), 代碼中,若文件創(chuàng)建打開(kāi)有任何問(wèn)題,Open函數(shù)將在它的最后一個(gè)參數(shù)中返回CFileException(文件異常類(lèi))對(duì)象,TRACE宏將顯示出文件名和表示失敗原因的代碼。使用AfxTh

22、rowFileException函數(shù)將獲得更詳細(xì)的有關(guān)錯(cuò)誤的報(bào)告。 與文件“打開(kāi)”相反的操作是“關(guān)閉”,可以使用Close函數(shù)來(lái)關(guān)閉一個(gè)文件對(duì)象,若該對(duì)象是在堆內(nèi)存中創(chuàng)建的,還需調(diào)用delete來(lái)刪除它(不是刪除物理文件)。,6.3使用CFile類(lèi),6.3.2 文件的讀寫(xiě)和定位 CFile類(lèi)支持文件的讀、寫(xiě)和定位操作。它們相關(guān)函數(shù)的原型如下: UINT Read( void* lpBuf, UINT nCount ); 此函數(shù)將文件中指定大小的數(shù)據(jù)讀入指定的緩沖區(qū),并返回向緩沖區(qū)傳輸?shù)淖止?jié)數(shù)。需要說(shuō)明的是,這個(gè)返回值可能小于nCount,這是因?yàn)榭赡艿竭_(dá)了文件的結(jié)尾。 void Write(

23、const void* lpBuf, UINT nCount ); 此函數(shù)將緩沖區(qū)的數(shù)據(jù)寫(xiě)到文件中。參數(shù)lpBuf用來(lái)指定要寫(xiě)到文件中的數(shù)據(jù)緩沖區(qū)的指針,nCount表示從數(shù)據(jù)緩沖區(qū)傳送的字節(jié)數(shù)。對(duì)于文本文件,每行的換行符也被計(jì)算在內(nèi)。 LONG Seek( LONG lOff, UINT nFrom ); 此函數(shù)用來(lái)定位文件指針的位置,若要定位的位置是有效的,則此函數(shù)將返回從文件開(kāi)始的偏移量。否則,返回值是不定的且激活一個(gè)CFileException對(duì)象。參數(shù)lOff用來(lái)指定文件指針移動(dòng)的字節(jié)數(shù),nFrom表示指針移動(dòng)方式,它可以是CFile:begin(從文件的開(kāi)始位置)、CFile:cu

24、rrent(從文件的當(dāng)前位置)或CFile:end(從文件的最后位置,但lOff必須為負(fù)值才能在文件中定位,否則將超出文件)等。需要說(shuō)明的是,文件剛打開(kāi)時(shí),默認(rèn)的文件指針位置為0,即文件的開(kāi)始位置。 另外,函數(shù)void SeekToBegin( )和DWORD SeekToEnd( )分別將文件指針移動(dòng)到文件開(kāi)始和結(jié)尾位置,對(duì)于后者還將返回文件的大小。,6.3使用CFile類(lèi),6.3.3 獲取文件的有關(guān)信息 CFile 還支持獲取文件狀態(tài),包括文件是否存在、創(chuàng)建與修改的日期和時(shí)間、邏輯大小和路徑等。 BOOL GetStatus( CFileStatus 若指定文件的狀態(tài)信息成功獲得,該函數(shù)返

25、回TRUE,否則返回FALSE。其中,參數(shù)lpszFileName用來(lái)指定一個(gè)文件路徑,這個(gè)路徑可以是相對(duì)的或是絕對(duì)的,但不能是 網(wǎng)絡(luò)文件名。rStatus用來(lái)存放文件狀態(tài)信息,它是一個(gè)CFileStatus結(jié)構(gòu)類(lèi)型,該結(jié)構(gòu)具 有下列成員: CTime m_ctime 文件創(chuàng)建日期和時(shí)間 CTime m_mtime 文件最后一次修改日期和時(shí)間 CTime m_atime 文件最后一次訪問(wèn)日期和時(shí)間 LONGm_size 文件大小的字節(jié)數(shù) BYTE m_attribute 文件屬性 char m_szFullName_MAX_PATH 文件名,6.3使用CFile類(lèi),需要說(shuō)明的是,static形

26、式的GetStatus函數(shù)將獲得指定文件名的文件狀態(tài),并將文件名復(fù)制至m_szFullName中。該函數(shù)僅獲取文件狀態(tài),并沒(méi)有真正打開(kāi)文件,這對(duì)于測(cè)試一個(gè)文件的存在性是非常有用的。例如下面的代碼: CFile theFile; char* szFileName = c:testmyfile.dat; BOOL bOpenOK; CFileStatus status; if( CFile:GetStatus( szFileName, status ) ) / 該文件已存在,直接打開(kāi) bOpenOK = theFile.Open( szFileName, CFile:modeWrite ); el

27、se / 該文件不存在,需要使用modeWrite方式創(chuàng)建它 bOpenOK = theFile.Open( szFileName, CFile:modeCreate | CFile:modeWrite ); ,6.3使用CFile類(lèi),6.3.4 CFile示例 如圖6.2所示,單擊瀏覽按鈕,將彈出文件“打開(kāi)”對(duì)話框,從中選擇一個(gè)文件時(shí),編輯框上方顯示出該文件的路徑名、創(chuàng)建時(shí)間和文件大小,并在編輯框中顯示出該文件的內(nèi)容。,圖6.2 CFile示例運(yùn)行結(jié)果,6.3使用CFile類(lèi),例Ex_File 使用CFile (1)創(chuàng)建一個(gè)默認(rèn)的對(duì)話框應(yīng)用程序Ex_File。 (2)將對(duì)話框的標(biāo)題設(shè)為“使用

28、CFile”。刪除“TODO: 在這里設(shè)置對(duì)話控制?!膘o態(tài)文本控件和 取消按鈕,將確定按鈕標(biāo)題改為“退出”。 (3)打開(kāi)對(duì)話框網(wǎng)格,參看圖6.2的控件布局,添加靜態(tài)文件控件IDC_STATIC_TITLE(選中“垂直居中”和“凹陷”選項(xiàng))、一個(gè)編輯框IDC_EDIT1(選中“多行”、“水平滾動(dòng)”、“垂直滾動(dòng)”和“自動(dòng)垂直滾動(dòng)”選項(xiàng))和一個(gè)“打開(kāi)”按鈕IDC_BUTTON_OPEN。 (4)打開(kāi)MFC ClassWizard的Member Variables頁(yè)面,為IDC_STATIC_TITLE控件添加Value類(lèi)型變量m_strTitle,為IDC_EDIT1控件添加Value類(lèi)型變量m_s

29、trContent。 (5)再次打開(kāi)MFC ClassWizard,切換到Messsage Maps頁(yè)面,為CEx_FileDlg類(lèi)添加按鈕IDC_BUTTON_OPEN 的BN_CLICKED消息映射,保留默認(rèn)的映射函數(shù)名,并添加下列代碼: (6)編譯運(yùn)行并測(cè)試。,6.4文檔序列化,6.4.1 文檔模板和字串資源 1. 文檔模板 文檔應(yīng)用程序框架是在程序運(yùn)行時(shí)就開(kāi)始構(gòu)造的,在單文檔應(yīng)用程序(設(shè)為Ex_SDI)的應(yīng)用程序類(lèi)InitInstance函數(shù)中,可以看到這樣的代碼: BOOL CEx_SDIApp:InitInstance() CSingleDocTemplate* pDocTempl

30、ate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME,/ 資源ID RUNTIME_CLASS(CEx_SDIDoc),/ 文檔類(lèi) RUNTIME_CLASS(CMainFrame), / 主框架窗口類(lèi) RUNTIME_CLASS(CEx_SDIView);/ 視圖類(lèi) AddDocTemplate(pDocTemplate); return TRUE; ,6.4文檔序列化,類(lèi)似的,多文檔模板類(lèi)CMultiDocTemplate的構(gòu)造函數(shù)也有相同的定義。如下面的代碼(設(shè)為Ex_MDI): BOOL CEx_MDIApp:InitIns

31、tance() CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_EX_MDITYPE,/ 資源ID RUNTIME_CLASS(CEx_MDIDoc),/ 文檔類(lèi) RUNTIME_CLASS(CChildFrame), / MDI文檔窗口類(lèi) RUNTIME_CLASS(CEx_MDIView);/ 視圖類(lèi) AddDocTemplate(pDocTemplate); / 創(chuàng)建主框架窗口 CMainFrame* pMainFrame = new CMainFrame; if (!pMainFram

32、e-LoadFrame(IDR_MAINFRAME) return FALSE; m_pMainWnd = pMainFrame; return TRUE; ,6.4文檔序列化,2. 文檔模板字串資源 從前面的單文檔模板類(lèi)可以看出,為了能將菜單、加速鍵、圖標(biāo)等資源加載到應(yīng)用程序框架中,這些資源的標(biāo)識(shí)符都設(shè)為了IDR_MAINFRAME。事實(shí)上,在MFC文檔序列化流程(后面會(huì)討論到)中,文檔標(biāo)題和通用文件“打開(kāi)”和“保存”對(duì)話框的過(guò)濾器中文件類(lèi)型還必需能夠在相關(guān)的資源給予指定,這個(gè)資源就是文檔模板字串資源,它是String Table(字符串)資源列表中的IDR_MAINFRAME項(xiàng),其內(nèi)容如下

33、(以單文檔應(yīng)用程序Ex_SDI為例): Ex_SDInnEx_SDInnnExSDI.DocumentnEx_SDI Document 可以看出,IDR_MAINFRAME所標(biāo)識(shí)的字符串被分成了一些以“n”結(jié)尾的子串,這些子串共有7段,每段都有特定的用途,其含義如表6.2所示。,6.4文檔序列化,表6.2 文檔模板字符串的含義,6.4文檔序列化,但對(duì)于MDI來(lái)說(shuō),上述的字串分別由IDR_MAINFRAME和IDR_EX_MDITYPE(若項(xiàng)目名為Ex_MDI)組成;其中,IDR_MAINFRAME表示窗口標(biāo)題,而IDR_EX_MDITYPE表示后6項(xiàng)內(nèi)容。它們的內(nèi)容如下: IDR_MAINFR

34、AME:Ex_MDI圖6.3 Advanced Options對(duì)話框5036214 IDR_EX_MDITYPE:nEx_MDInEx_MDInnnExMDI.DocumentnEx_MDI Document 實(shí)際上,文檔模板字串資源內(nèi)容既可直接通 過(guò)上述字串資源編輯器進(jìn)行修改,也可以在文檔 應(yīng)用程序創(chuàng)建向?qū)У牡谒牟街?,單擊高?jí)按鈕, 通過(guò)“高級(jí)選項(xiàng)(Advanced Options)”對(duì)話框 中的“文檔字符模板(Document Template Strings) ”頁(yè)面來(lái)指定,如圖6.3所示(以單文檔應(yīng)用程序 Ex_SDI為例)。圖中的數(shù)字表示該項(xiàng)的含義與 表6.3中對(duì)應(yīng)串號(hào)的含義相同。,

35、6.4文檔序列化,6.4.2 文檔序列化過(guò)程 MFC文檔序列化過(guò)程包括:創(chuàng)建空文檔、打開(kāi)文檔、保存文檔和關(guān)閉文檔這幾個(gè)操作,下面來(lái)闡述它們的具體運(yùn)行過(guò)程。 1. 創(chuàng)建空文檔 應(yīng)用程序類(lèi)的InitInstance函數(shù)在調(diào)用了AddDocTemplate函數(shù)之后,會(huì)通過(guò)CWinApp: ProcessShellCommand間接調(diào)用CWinApp的另一個(gè)非常有用的成員函數(shù)OnFileNew,并依次完成下列工作: (1)構(gòu)造文檔對(duì)象,但并不從磁盤(pán)中讀數(shù)據(jù)。 (2)構(gòu)造主框架類(lèi)CMainFrame的對(duì)象,并創(chuàng)建該主框架窗口,但不顯示。 (3)構(gòu)造視圖對(duì)象,并創(chuàng)建視圖窗口,也不顯示。 (4)通過(guò)內(nèi)部機(jī)制

36、,使文檔、主框架和視圖“對(duì)象”之間“真正”建立聯(lián)系。注意與 AddDocTemplate函數(shù)的區(qū)別,AddDocTemplate函數(shù)建立的是“類(lèi)”之間的聯(lián)系。 (5)調(diào)用文檔對(duì)象的CDocument:OnNewDocument虛函數(shù),并調(diào)用CDocument: DeleteContents虛函數(shù)來(lái)清除文檔對(duì)象的內(nèi)容。,6.4文檔序列化,(6)調(diào)用視圖對(duì)象的CView:OnInitialUpdate虛函數(shù)對(duì)視圖進(jìn)行初始化操作。 (7)調(diào)用框架對(duì)象的CFrameWnd:ActiveFrame虛函數(shù),以便顯示出帶有菜單、工具欄、狀態(tài)欄以及視圖窗口的主框架窗口。 在單文檔應(yīng)用程序中,文檔、主框架以及視

37、圖對(duì)象僅被創(chuàng)建一次,并且這些對(duì)象在整個(gè)運(yùn)行過(guò)程中都有效。CWinApp:OnFileNew函數(shù)被InitInstance函數(shù)所調(diào)用。但當(dāng)用戶選擇“文件(File)”菜單中的“新建(New)”時(shí),CWinApp:OnFileNew也會(huì)被調(diào)用,但與InitInstance不同的是,這種情況下不再創(chuàng)建文檔、主框架以及視圖對(duì)象,但上述過(guò)程的最后三個(gè)步驟仍然會(huì)被執(zhí)行。 2. 打開(kāi)文檔 當(dāng)MFC AppWizard創(chuàng)建應(yīng)用程序時(shí),它會(huì)自動(dòng)將“文件(File)”菜單中的“打開(kāi)(Open)”命令(ID號(hào)為ID_FILE_OPEN)映射到CWinApp的OnFileOpen成員函數(shù)。這一結(jié)果可以從應(yīng)用類(lèi)(.cp

38、p)的消息入口處得到驗(yàn)證: BEGIN_MESSAGE_MAP(CEx_SDIApp, CWinApp) ON_COMMAND(ID_FILE_NEW, CWinApp:OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp:OnFileOpen) / Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp:OnFilePrintSetup) END_MESSAGE_MAP() OnFileOpen函數(shù)還會(huì)進(jìn)一步完成下列工作:,6.4文檔序列化,(1)彈出通用文件“打開(kāi)”對(duì)話框,供

39、用戶選擇一個(gè)文檔。 (2)文檔指定后,調(diào)用文檔對(duì)象的CDocument: OnOpenDocument虛函數(shù)。該函數(shù)將打開(kāi)文檔,并調(diào)用DeleteContents清除文檔對(duì)象的內(nèi)容,然后創(chuàng)建一個(gè)CArchive對(duì)象用于 數(shù)據(jù)的讀取,接著又自動(dòng)調(diào)用Serialize函數(shù)。 (3)調(diào)用視圖對(duì)象的CView:OnInitialUpdate虛函數(shù)。 除了使用“文件(File)”“打開(kāi)(Open)”菜單項(xiàng)外,用戶也可以選擇最近使用過(guò)的文件列表來(lái)打開(kāi)相應(yīng)的文檔。在應(yīng)用程序的運(yùn)行過(guò)程中,系統(tǒng)會(huì)記錄下4個(gè)默認(rèn)最近使用過(guò)的文件,并將文件名保存在Windows的注冊(cè)表中。當(dāng)每次啟動(dòng)應(yīng)用程序時(shí),應(yīng)用程序都會(huì)最近使用

40、過(guò)的文件名稱(chēng)顯示在“文件(File)”菜單中。 3. 保存文檔 (1)當(dāng)MFC AppWizard創(chuàng)建應(yīng)用程序時(shí),它會(huì)自動(dòng)將“文件(File)”菜單中的“保存(Save)”命令與文檔類(lèi)CDocument的OnFileSave函數(shù)在內(nèi)部關(guān)聯(lián)起來(lái),但用戶在程序框架中看不到相應(yīng)的代碼。OnFileSave函數(shù)還會(huì)進(jìn)一步完成下列工作: (2)彈出通用文件“保存”對(duì)話框,讓用戶提供一個(gè)文件名。 (3)調(diào)用文檔對(duì)象的CDocument:OnSaveDocument虛函數(shù),接著又自動(dòng)調(diào)用Serialize函數(shù),將CArchive對(duì)象的內(nèi)容保存在文檔中。,6.4文檔序列化,需要說(shuō)明的是: 只有在保存文檔之前還

41、沒(méi)有存過(guò)盤(pán)(亦即沒(méi)有文件名)或讀取的文檔是“只讀”的, OnFileSave函數(shù)才會(huì)彈出通用“保存”對(duì)話框。否則,只執(zhí)行第二步。 “文件(File)”菜單中還有一個(gè)“另存為(Save As)”命令,它是與文檔類(lèi)CDocument的 OnFileSaveAs函數(shù)相關(guān)聯(lián)。不管文檔有沒(méi)有保存過(guò),OnFileSaveAs都會(huì)執(zhí)行上述兩個(gè)步驟。 上述文檔存盤(pán)的必要操作都是由系統(tǒng)自動(dòng)完成的。 4. 關(guān)閉文檔 當(dāng)用戶試圖關(guān)閉文檔(或退出應(yīng)用程序)時(shí),應(yīng)用程序會(huì)根據(jù)用戶對(duì)文檔的修改與否來(lái)進(jìn)一步完成下列任務(wù): (1)若文檔內(nèi)容已被修改,則彈出一個(gè)消息對(duì)話框,詢問(wèn)用戶是否需要將文檔保存。當(dāng)用戶選擇“是”,則應(yīng)用程

42、序執(zhí)行OnFileSave過(guò)程。 (2)調(diào)用CDocument:OnCloseDocument虛函數(shù),關(guān)閉所有與該文檔相關(guān)聯(lián)的文檔窗口及相應(yīng)的視圖,調(diào)用文檔類(lèi)CDocument的DeleteContents清除文檔數(shù)據(jù)。,6.4文檔序列化,6.4.3 CArchive類(lèi)和序列化操作 從上述的單文檔序列化過(guò)程可以看出:打開(kāi)和保存文檔時(shí),系統(tǒng)都會(huì)自動(dòng)調(diào)用Serialize函數(shù)。事實(shí)上,MFC AppWizard在創(chuàng)建文檔應(yīng)用程序框架時(shí)已在文檔類(lèi)中重載了Serialize函數(shù),通過(guò)在該函數(shù)中添加代碼可達(dá)到實(shí)現(xiàn)數(shù)據(jù)序列化的目的。例如,在Ex_SDI單文檔應(yīng)用程序的文檔類(lèi)中有這樣的默認(rèn)代碼: void

43、CEx_SDIDoc:Serialize(CArchive/ 讀寫(xiě)數(shù)據(jù)時(shí)使用 CString m_strArchive; / 讀寫(xiě)數(shù)據(jù)時(shí)使用 BOOL m_bIsMyDoc;/ 用于判斷文檔 (4)在CEx_SDIArchiveDoc類(lèi)構(gòu)造函數(shù)中添加下列代碼: CEx_SDIArchiveDoc:CEx_SDIArchiveDoc() m_bIsMyDoc = FALSE; (5)在CEx_SDIArchiveDoc:OnNewDocument函數(shù)中添加下列代碼: BOOL CEx_SDIArchiveDoc:OnNewDocument() if (!CDocument:OnNewDocume

44、nt() return FALSE; strcpy(m_chArchive, ,6.4文檔序列化,(6)在CEx_SDIArchiveDoc:Serialize函數(shù)中添加下列代碼: (7)編譯運(yùn)行并測(cè)試。程序運(yùn)行后,選擇“文件”“另存為”菜單,指定一個(gè)文檔名1.my,然后選擇“文件”“新建”菜單,再打開(kāi)該文檔,結(jié)果就會(huì)彈出對(duì)話框,顯示該文檔的內(nèi)容,如圖6.4所示。,圖6.4 顯示文檔內(nèi)容,6.4文檔序列化,6.4.4 CArchive類(lèi)和CFile類(lèi)關(guān)聯(lián) 事實(shí)上,文檔應(yīng)用程序框架就是將一個(gè)外部磁盤(pán)文件和一個(gè)CArchive 對(duì)象關(guān)聯(lián)起來(lái)。當(dāng)然,這種關(guān)聯(lián)還可直接通過(guò)CFile來(lái)進(jìn)行。例如: CF

45、ile theFile; theFile.Open(., CFile:modeWrite); CArchive archive(,6.5綜合應(yīng)用,在用文件來(lái)存取數(shù)據(jù)時(shí),最大的難度是要保證讀取的數(shù)據(jù)的正確性。若有一個(gè)記錄結(jié)構(gòu),包括學(xué)生的姓名(字符串)、學(xué)號(hào)(字符串)以及三門(mén)課程成績(jī),則如何保證在文件讀寫(xiě)的正確性呢?一種辦法是將記錄定義成C結(jié)構(gòu)體類(lèi)型,使用CFile來(lái)操作,這是避開(kāi)MFC文檔序列化機(jī)制而進(jìn)行的方法,雖有效但缺少對(duì)MFC機(jī)制和類(lèi)的應(yīng)用,因?yàn)樵贑+中,C結(jié)構(gòu)體被看作是類(lèi)的一種簡(jiǎn)單形式。另一種方法,是將記錄聲明成一個(gè)類(lèi),并使該類(lèi)具體可序列化特性。一個(gè)可序列化的類(lèi)的對(duì)象可以在Seriali

46、ze函數(shù)使用CArchive對(duì)象通過(guò)“”來(lái)正確地向文件進(jìn)行寫(xiě)入和讀取操作。,圖6.5 Ex_Student運(yùn)行結(jié)果,6.5綜合應(yīng)用,下面來(lái)看一個(gè)綜合應(yīng)用,如圖6.5所示。它首先通過(guò)對(duì)話框來(lái)輸入一個(gè)學(xué)生記錄,記錄包括學(xué)生的姓名、學(xué)號(hào)和三門(mén)成績(jī),用類(lèi)CStudent來(lái)描述,并使其可序列化。然后將記錄內(nèi)容保存到一個(gè)對(duì)象數(shù)組集合類(lèi)對(duì)象中,最后通過(guò)文檔序列化將記錄保存到一個(gè)文件中。當(dāng)添加記錄或打開(kāi)一個(gè)記錄文件,還會(huì)將數(shù)據(jù)顯示在文檔窗口(即視圖)中。 例Ex_Student 文檔序列化示例 1)添加用于學(xué)生記錄輸入的對(duì)話框 (1)創(chuàng)建一個(gè)默認(rèn)的單文檔應(yīng)用程序Ex_Student。 (2)向應(yīng)用程序中添加一

47、個(gè)對(duì)話框資源,打開(kāi)屬性對(duì)話框?qū)⑵渥煮w設(shè)置為“宋體,9”,標(biāo)題改為“添加學(xué)生記錄”,取默認(rèn)的ID號(hào)IDD_DIALOG1,將OK和Cancel按鈕的標(biāo)題分別改為“確 定”和“取 消”。 (3)參看圖6.5的控件布局,用編輯器為對(duì)話框添加如下表6.4所示的一些控件。,6.5綜合應(yīng)用,表6.4 添加的控件,6.5綜合應(yīng)用,(4)雙擊對(duì)話框模板或按Ctrl+W快捷鍵,為對(duì)話框資源IDD_DIALOG1創(chuàng)建一個(gè)對(duì)話框類(lèi)CInputDlg。 (5)打開(kāi)ClassWizard的Member Variables標(biāo)簽,在Class name中選擇CInputDlg,選中所需的控件ID標(biāo)識(shí)符,雙擊鼠標(biāo)或單擊Add

48、 Variables按鈕。依次為表6.5控件增加成員變量。,表6.5 控件變量,6.5綜合應(yīng)用,2)添加一個(gè)CStudent類(lèi)并使該類(lèi)可序列化 一個(gè)可序列化的類(lèi)必須是CObject的一個(gè)派生類(lèi),且在類(lèi)聲明中,需要包含DECLARE_SERIAL宏調(diào)用,而在類(lèi)的實(shí)現(xiàn)文件中包含IMPLEMENT_SERIAL宏調(diào)用,這個(gè)宏有3個(gè)參數(shù):前2個(gè)參數(shù)分別表示類(lèi)名和基類(lèi)名,第3個(gè)參數(shù)表示應(yīng)用程序的版本號(hào)。最后還需要重載Serialize函數(shù),使該類(lèi)的數(shù)據(jù)成員進(jìn)行相關(guān)序列化操作。 由于使用ClassWizard無(wú)法添加一個(gè)CObject派生類(lèi),因此必須手動(dòng)進(jìn)行。為了簡(jiǎn)化類(lèi)文件的復(fù)雜性,這里創(chuàng)建的這個(gè)CStu

49、dent類(lèi)的聲明和實(shí)現(xiàn)代碼是直接添加在Ex_StudentDoc.h和Ex_StudentDoc.cpp文件中的,具體如下: 3)添加并處理菜單項(xiàng) (1)在菜單資源的主菜單中增加頂層菜單項(xiàng)“學(xué)生記錄( if (IDOK = dlg.DoModal() / 添加記錄 CStudent *pStudent = new CStudent(dlg.m_strName, dlg.m_strID, dlg.m_fScore1, dlg.m_fScore2, dlg.m_fScore3); m_stuObArray.Add(pStudent); SetModifiedFlag();/ 設(shè)置文檔更改標(biāo)志 UpdateAllViews(NULL);/ 更新視圖 (3)在Ex_StudentDoc.cpp文件的開(kāi)始處,增加包含CAddDlg的頭文件。 #include Ex_StudentDoc.h

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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)論