460 likes | 775 Views
第 9 章 MFC 通用类. MFC 类库除了提供封装 Windows 界面元素对象的类,如 CWnd 、 CMenu 、 CDialog 等,还提供了一些通用的类。本章主要叙述字符串类、日期时间类和集合类的使用及主要成员函数,最后结合实例,说明使用该类的方法和技巧。. 9.1 字符串类- Cstring 1 .创建 CString 类对象 CString 类构造函数的版本很多,它们的函数原型如下: CString( ); // 构造空字符串
E N D
MFC类库除了提供封装Windows界面元素对象的类,如CWnd、CMenu、CDialog等,还提供了一些通用的类。本章主要叙述字符串类、日期时间类和集合类的使用及主要成员函数,最后结合实例,说明使用该类的方法和技巧。
9.1 字符串类-Cstring 1.创建CString类对象 CString类构造函数的版本很多,它们的函数原型如下: CString( ); //构造空字符串 CString( const CString& stringSrc ); //拷贝已有字符串内容,构造新的字符串 CString( TCHAR ch, int nRepeat = 1 ); //用重复的字符构造新的字符串,字符由参数ch表明,重复次数由nRepeat决定
CString( LPCTSTR lpch, int nLength ); //拷贝字符数组的内容构造字符串,lpch为指向数组的指针,nLength为数组长度 CString( const unsigned char* psz ); //拷贝以'\0'结尾的字符串内容,构造新的字符串,psz为指向字符串的指针 CString( LPCWSTR lpsz ); CString( LPCSTR lpsz ); //拷贝lpsz指定字符串内容构造Unicode字符串
2.有关数组属性的成员函数和操作符 (1)int GetLength( ) const; 函数返回字符串对象中的字符数,不包括最后的\‘0’。 (2)BOOL IsEmpty( ) const; 函数判断字符串对象是否为空,即包含的字符数为0。如果为空,返回值为TRUE,否则,返回值为FALSE。 (3)void Empty( ); 函数强制清空字符串对象,使其包含的字符数为0。清空字符串对象后,调用GetLength函数的返回值为0。
(4)TCHAR GetAt( int nIndex ) const; 函数返回字符串对象中由nIndex索引值指定单个字符,索引以0为基础,第一个字符对应的索引值为0。nIndex的值必须大于或等于0,小于字符串中字符的总数,在MFC调试版本中,程序将检测nIndex是否为合法值,而在Release版本中,将不进行检测。 (5)operator LPCTSTR ( ) const; 操作符返回一个指向包含在CString类对象中的以‘\0’结尾的字符串的const char *指针,返回的指针是只读的,不能对其进行修改。
3.CString类的表达式 CString类重载了“=”、“+”、“+=”三个运算符,以实现字符串之间的赋值和串联运算。 4.比较类函数及操作符 (1)比较操作符 CString类重载了“==”、“!=”、“>”、“<”、“>=”、“<=”操作符,以实现对字符串的比较操作,可以进行字符串对象之间、字符串对象和LPCTSTR字符串、字符串对象和字符指针之间的比较,比较操作是大小写敏感的。 (2)int Compare( LPCTSTR lpsz ) const; 将字符串类对象与lpsz比较,如果相等,返回值为0;如果比lpsz大,返回值大于0;如果比lpsz小,返回值小于0。
5.字符串截取类函数 (1)CString Left( int nCount ) const; Left函数提取字符串对象最开始(左侧)的若干字符,将所提取子串的拷贝作为返回值。截取字符的数量由参数nCount决定,当nCount大于字符串长度时,整个字符串被提取。操作后,原始字符串未发生变化。 (2)CString Right( int nCount ) const; 与Left函数调用类似,Right函数调用提取字符串右侧(末尾)的若干字符。 (3)CString Mid( int nFirst ) const; CString Mid( int nFirst, int nCount ) const; Mid函数调用从字符串对象中间开始提取子串,开始位置由nFirst参数指定,提取字符数由参数nCount指定,当省略参数nCount,表示从nFirst开始,提取余下的所有字符。 CString s1( "abcdef" ); CString s2= s.Mid( 2,3 ); // s2= "cde"
6.转换函数 (1)void MakeUpper( ); 将字符串中的所有小写字母转换为大写。 (2)void MakeLower( ); 将字符串中的所有大写字母转换为小写。 (3)void MakeReverse( ); 反转字符串对象中所有字符的排列顺序。 (4)int Replace( TCHAR chOld, TCHAR chNew ); int Replace( LPCTSTR lpszOld, LPCTSTR lpszNew ); (5)int Insert( int nIndex, TCHAR ch ) int Insert( int nIndex, LPCTSTR pstr ) 函数从指定的位置,插入一个字符或字符串,插入位置由nIndex参数指定,插入内容由ch或pstr指定,返回值为插入后新字符串的长度。
(6)int CString::Remove( TCHAR ch ); 函数清除字符串对象中由ch指定的所有字符,返回值为删除的总字符数,如果没有匹配的字符,返回值为0。字符匹配是大小写敏感的。 (7)int Delete( int nIndex, int nCount = 1 ) 函数删除字符串中连续的若干字符,删除的起始位置由nIndex参数决定,删除的字符数由参数nCount决定,如果nCount大于从nIndex开始余下的字符数,则余下的所有字符被删除。返回值为删除部分字符后字符串的长度。
(8)void TrimRight( ); void TrimRight( TCHAR chTarget ); void TrimRight( LPCTSTR lpszTargets ); 没有参数的函数版本清除字符串结尾处的连续空白字符,包括换行符、空格、制表符直至遇到非空白字符为止。调用带参数的版本清除字符串结尾处所有指定的字符或字符串。 (9)格式化字符串 void Format( LPCTSTR lpszFormat, ... ); 函数用来格式化字符串,参数lpszFormat为格式化控制字符串,省略号表示lpszFormat中指定的参数列表,具体格式控制与printf函数类似,请参考有关手册。
7.查找类成员函数 CString类中成员函数Find用来查找字符串中第一个匹配的字符或字符子串。函数返回第一个匹配字符或子串的起始位置,如果没有匹配子串或字符,返回-1,它的原型有4种。 int Find( TCHAR ch ) const; 参数ch指定要匹配的字符。 int Find( LPCTSTR lpszSub ) const; 参数lpszSub指定要匹配的字符串。 int Find( TCHAR ch, int nStart ) const; int Find( LPCTSTR pstr, int nStart ) const;
8.有关缓冲区的操作 使用缓冲区来操作字符串内容应遵循下面的步骤: (1)调用GetBuffer函数,得到指向字符串缓冲区的指针; (2)直接修改指向缓冲区指针所指的内容,以达到间接修改字符串对象的目的; (3)调用ReleaseBuffer函数,以结束缓冲区的使用。 9.BOOL LoadString( UINT nID );
9.2 日期和时间类 MFC提供了CTime和CTimeSpan类,以方便在应用程序中处理跟时间有关的数据。这两个类实现了ANSI时间函数(通常包含在time.h头文件中)的大部分功能,并简化了操作。我们也可以直接使用这些ANSI时间函数来处理时间数据。
9.2.1 CTime类及其主要成员函数 1.CTime类的常用构造函数 CTime( ); 构造未初始化的时间对象,使用前,一定要初始化。 CTime( const CTime& timeSrc ); 从现有的时间类对象构造新的时间类对象。 CTime( time_t time ); 从time_t类型变量构造时间类对象。 CTime( int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, int nDST = -1 ); 通过指定年、月、日、小时、分、秒各分量来构造时间类对象。
2.提取时间信息的有关函数 (1)time_t GetTime( ) const; 从CTime类对象中提取time_t类型时间值。 (2)提取时间值:年、月、日、小时、分、秒、星期 int GetYear( ) const; 返回值范围1970~2038; int GetMonth( ) const; 返回值范围1~12; int GetDay( ) const; 返回值范围1~31; int GetHour( ) const; 返回值范围0~23; int GetMinute( ) const; 返回值范围0~59; int GetSecond( ) const; 返回值范围0~59; int GetDayOfWeek( ) const; 返回值范围1~7,1表示星期一,二为星期二,依此类推。
3.重载的运算符 (1)赋值运算符(=),用于将CTime对象或time_t变量赋给另一个CTime对象; (2)可以使用==、!=、<、>、<=、>=等操作符来比较两个CTime对象。往后的时间值比前面的时间值大; (3)可以使用+、-、+=、-=运算符向CTime类对象加入或减去一个CTimeSpan对象; (4)可以从一个CTime对象中减去另一个CTime对象,以得到CTimeSpan对象;
4.格式化时间 通过Format成员函数可以从CTime对象中创建一个格式化的CString对象,原型如下: CString Format( LPCTSTR pFormat ) const;
9.2.2 CTimeSpan类及其主要成员函数 1.常用的构造函数 CTimeSpan( ); 构造未初始化的CTimeSpan对象 CTimeSpan( const CTimeSpan& timeSpanSrc ); 拷贝现有CTimeSpan对象的值,构造新的CTimeSpan对象 CTimeSpan( time_t time ); 使用time_t类型(长整型)数值,构造CTimeSpan对象,time为时间差的秒数 CTimeSpan( LONG lDays, int nHours, int nMins, int nSecs );
2.提取时间信息 (1)GetDays、GetHours、GetMinutes、GetSeconds用于提取CTimeSpan对象中的天数、小时数、分钟数以及秒数,其原型如下: LONG GetDays( ) const; GetDays用于返回总的天数。 int GetHours( ) const; Get Hours用于返回当天的小时数,取值范围为-23~23。 int Get Minutes( ) const; Get Minutes用于返回当前小时内的分钟数,取值范围为-59~59。
(2)使用GetTotalHours、GetTotalMinutes、GetTotalSeconds提取CTimeSpan对象中的时间,并折合成总的小时数、分钟数以及秒数,其原型如下:(2)使用GetTotalHours、GetTotalMinutes、GetTotalSeconds提取CTimeSpan对象中的时间,并折合成总的小时数、分钟数以及秒数,其原型如下: LONG GetTotalHours( ) const; LONG GetTotalMinutes( ) const; LONG GetTotalSeconds( ) const;
3.重载运算符 CTimeSpan重载了==、!=、<、>、<=、>=运算符,以实现CTimeSpan对象之间的比较; CTimeSpan重载了赋值(=)运算符,以进行CTimeSpan对象之间相互赋值; CTimeSpan重载了+、-、+=、-=运算符,以实现两个CTimeSpan对象之间的运算。
4.格式化时间 CString Format( LPCSTR pFormat ) const; 函数调用将CTimeSpan类对象中的时间信息按指定的格式输出到字符串中,输出格式由参数pFormat指定,格式代码由%作为前导符号,具体输出时,由相应的时间分量替代,其它字符,原样输出到字符串中。
9.2.3 COleDateTime与COleDateTimeSpan类介绍 COleDateTime与COleDateTimeSpan类的使用与CTime和CTimeSpan类的使用类似,成员函数及调用方法也非常类似,可以相互参考。COleDateTime与COleDateTimeSpan为OLE对象,使用时要包含相应的头文件“afxdisp.h”,它们所表示的时间范围比CTime及CTimeSpan类要大,在实际使用过程中,可以灵活掌握。这里,不再重复列出它们的成员函数及操作符,具体使用细节请参考MSDN的有关内容。
9.3 集合类的使用 MFC提供了两种集合类,一种是基于模板的集合类,一种是非模板集合类,两种类都可以实现列表、数组和映象。对于非模板集合类,MFC提供了许多预定义的类,分别用来实现列表、数组和映象。 MFC提供了CPtrList类处理void型指针列表,CStringList类存储CString类型列表,CObList类存储指向CObject派生对象的指针列表。 MFC提供的存储简单值类型的数组类有:CByteArray、CWordArray、CUintArray,提供了CPtrArray存储空指针数组,CStringArray保存CString类型数组,CObArray保存CObject指针数组。 MFC提供的预定义映象类有:CMapStringToString、CMapPtrToPtr、CMapStringToOb、CMapStringToPtr、CMapPtrToWord、CMapWordToOb、CMapWordToPtr。
9.3.1 数组类-Carray CArray的定义如下: template< class TYPE, class ARG_TYPE > class CArray : public CObject 参数TYPE指明数组中存储的数据类型,ARG_TYPE指明引用数组元素时使用的数据类型,通常为TYPE类型的引用。 CArray类类似于C中的数组,但能动态地调整内存分配,数组元素的索引从0开始。下面的语句定义了一个CArray类对象: CArray<CPoint,CPoint> m_ptArray; 其中存储数据的类型(即TYPE)为CPoint类型,引用数组元素的数据类型(即ARG_TYPE)也为CPoint类型。
1.有关属性的函数 (1)int GetSize( ) const; 用于返回数组中元素的个数。 (2)void SetSize( int nNewSize, int nGrowBy = -1 ); 设置空的或现存数组的大小,具体大小由参数nNewSize决定,nNewSize必须大于等于0,在必要时,会重新分配内存。 (3)int GetUpperBound( ) const; 用于返回当前数组对象可访问元素的索引上限,返回值比GetSize的返回值要小1,当返回值为-1,表示数组中没有元素。
2.访问数组元素 (1)TYPE GetAt( int nIndex ) const; 返回指定索引位置的数组元素值,具体位置由nIndex指定,它是以0为基础的,最大取值不得超过GetUpperBound的返回值。TYPE是数组元素的数据类型。以下函数的叙述中,TYPE含义相同。 (2)void SetAt( int nIndex, ARG_TYPE newElement ); 函数设置指定元素的值,索引位置由参数nIndex指定,新的元素值由newElement参数指定。ARG_TYPE为引用数组元素时的数据类型。以下函数中,ARG_TYPE含义相同。
(3)TYPE& ElementAt( int nIndex ); 返回由nIndex指定的数组元素引用,返回的引用值只能用于“左值”,用来间接修改数组元素的值,调用格式参见下面的示例代码。 (4)操作符[]类似C中的语法,可以替代SetAt、GetAt函数,提供简洁的数组访问方式。当数组对象被定义为const类型时,[]操作符只能用于“右值”。 (5)TYPE* GetData( ); 返回指向数组元素的指针,通过指针可以快速访问数组中的元素。对所返回指针的操作将直接影响数组元素的值。
3.增加、删除元素的有关操作 (1)int Add( ARG_TYPE newElement ); 向数组尾部增加一个新的数组元素,元素值为newElement,数组的大小将加1,返回值为插入的当前元素在数组中的索引位置。 (2)int Append( const CArray& src ); 将源数组src中的所有元素插入到当前数组的最后,两个数组的类型必须一致,函数会分配必要的内存以容纳新增的数组元素。返回值为第一个插入的数组元素的索引位置。 (3)void Copy( const CArray& src ); 将源数组src中的所有元素拷贝到当前数组中,并覆盖原有的数组元素,函数不会释放原有的内存,如果有必要,会分配额外的内存,以容纳新增的数组元素。
(4)void InsertAt( int nIndex, ARG_TYPE newElement, int nCount = 1 ); void InsertAt( int nStartIndex, CArray* pNewArray ); 第一个函数将在数组的指定位置插入一个数组元素或该元素值的多个拷贝,元素值由参数newElement指定,拷贝的份数由参数nCount指定。 第二个函数在数组的指定位置插入另一个数组中的元素,两个数组的类型必须一致。
(5)void RemoveAt( int nIndex, int nCount = 1 ); 删除数组中从指定位置开始的一个或多个元素,nIndex表明了起始位置,该值必须介于0至GetUpperBound函数返回值之间,删除后,余下的元素下移。此外,调用函数欲删除超过指定位置后余下的元素个数,将产生运行错误。 (6)void RemoveAll( ); 删除数组中的所有元素。
9.3.2 列表类-Clist 列表类的定义如下: template< class TYPE, class ARG_TYPE > class CList : public CObject 参数TYPE指明列表中存储的数据类型,参数ARG_TYPE指明引用列表元素时使用的数据类型。可以使用类型为POSITION的变量作为访问列表元素的关键字,可以通过该变量遍历列表项。
1.有关属性和状态的函数 (1)int GetCount() const; 返回列表中元素的个数。 (2)BOOL IsEmpty( ) const; 判断列表是否为空,即不包含任何元素。如果为空,返回TRUE,否则,返回FALSE。
2.获得表头和表尾函数 (1)获得表头 TYPE GetHead( ) const; TYPE& GetHead( ); 当定义的列表为const类型,返回值为列表表头元素的拷贝,可以使用该值作为“右值”,不可通过返回值间接修改对应的列表项。 当定义的列表不是const类型,返回值为列表头元素的引用,可以返回值作为赋值运算的左值或右值,可通过修改返回值间接修改列表元素的值。 (2)获得表尾 TYPE& GetTail( ); TYPE GetTail() const; GetTail函数与GetHead函数类似,用来返回表尾元素的引用或拷贝。
3.遍历列表元素 (1)获得列表表头元素的位置 POSITION GetHeadPosition( ) const; (2)获得指定位置处的列表元素并向前遍历 TYPE& GetNext( POSITION& rPosition ); TYPE GetNext( POSITION& rPosition ) const; (3)获得列表表尾元素的位置 POSITION GetTailPosition( ) const; (4)获得指定位置的列表元素并向后遍历 TYPE& GetPrev( POSITION& rPosition ); TYPE GetPrev( POSITION& rPosition ) const;
4.访问和操作列表元素 (1)TYPE& GetAt( POSITION position ); TYPE GetAt( POSITION position ) const; 函数返回由参数position指定位置元素的拷贝或引用,可以通过返回的引用间接修改列表元素的值。 (2)void SetAt( POSITION pos, ARG_TYPE newElement ); 函数设置指定位置处(由参数pos表明)的列表元素的值,所要设置的值由newElement参数指定。
5.增加删除元素操作 (1)POSITION AddHead( ARG_TYPE newElement ); void AddHead( CList* pNewList ); (2)POSITION AddTail( ARG_TYPE newElement ); void AddTail( CList* pNewList ); (3)TYPE RemoveHead( ); (4)TYPE RemoveTail( );
(5)void RemoveAt( POSITION position ); (6)void RemoveAll( ); (7)POSITION InsertBefore( POSITION position, ARG_TYPE newElement ); (8)POSITION InsertAfter( POSITION position, ARG_TYPE newElement );
6.查询操作 (1)POSITION Find( ARG_TYPE searchValue, POSITION startAfter = NULL) const; (2)POSITION FindIndex( int nIndex ) const;
9.3.3 映象类-CMap CMap类是以字典模式组织的集合类,它采用键(key)和键值(value)的配对来存储集合数据。键在集合中是唯一的,可以使用键来确定CMap对象中存储的特定元素,键值是运行重复的。 映象类的定义如下: template< class KEY, class ARG_KEY, class VALUE, class ARG_VALUE > class CMap : public CObject
1.有关状态的函数 (1)int GetCount( ) const; 调用函数获得CMap对象的元素(一个键与键值的配对)个数。 (2)BOOL IsEmpty( ) const; 调用函数判断CMap对象是否为空(没有元素),如果映象中不包含任何元素,函数返回TRUE,否则,返回FALSE。
2.遍历映象元素 (1)POSITION GetStartPosition( ) const; (2)void GetNextAssoc( POSITION& rNextPosition, KEY& rKey, VALUE& rValue ) const;
3.操作映象元素 (1)void SetAt( ARG_KEY key, ARG_VALUE newValue ); (2)BOOL Lookup( ARG_KEY key, VALUE& rValue ) const; (3)VALUE& operator[]( ARG_KEY key ); (4)BOOL RemoveKey( ARG_KEY key );
4.优化映象对象 (1)UINT GetHashTableSize( ) const; 函数获得映象中的元素个数。 (2)void InitHashTable( UINT hashSize ); 函数初始化映象对象,设置映象的初始大小。该函数应该在映象对象增加元素之前进行。
9.4 集合类应用的综合实例 9.4.1 创建基本应用程序 9.4.2 实现操作CArray类对象的视图类-CListView 9.4.3 实现操作CList对象的视图类-CIntListView 9.4.4 实现操作CMap对象的视图类-CMapView 9.4.5 在应用程序的“查看”菜单下添加若干菜单项 9.4.6 为各菜单建立消息映射,完成切换视图功能