第 9章 MFC通用类
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,BOOLLoadString( 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对象中的时间,并折合成总的小时数、分钟数以及秒数,其原型如下:
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 为各菜单建立消息映射,完成切换视图功能