Chapter 19

MFC Utility Classes


As you program with MFC, you run across many additional classes that, although not as immediately useful as something like the CWnd class, provide a convenient way to handle the various types of objects that are used in Windows programming. The most sophisticated of these utility classes is CString, which enables you to manipulate strings more easily. However, other classes, such as CPoint, CRect, CSize, and CTime, also do their part to make Windows programming with MFC quicker and more convenient. In this chapter, you learn about these helpful classes.

The CString Class

There are few programs that don't have to deal with text strings of one sort or another. Unfortunately, C++ is infamous for its difficult string-handling, whereas languages like BASIC and Pascal have always enjoyed superior power when it comes to these ubiquitous data types. MFC's CString class addresses C++'s string problems by providing member functions that are as handy to use as those found in other languages. Table 19.1 lists the commonly used member functions of the CString class.

Table 19.1 Commonly Used Member Functions of the CString Class

Function Description
Compare() Performs a case-sensitive comparison of two strings
CompareNoCase() Performs a case-insensitive comparison of two strings
Empty() Clears a string
Find() Locates a substring
GetAt() Gets a character at a specified position in the string
GetBuffer() Gets a pointer to the string's contents
GetLength() Gets the number of characters in the string
IsEmpty() Returns TRUE if the string holds no characters
Left() Gets the left segment of a string
MakeLower() Lowercases a string
MakeReverse() Reverses the contents of a string
MakeUpper() Uppercases a string
Mid() Gets the middle segment of a string
Right() Gets the right segment of a string
SetAt() Sets a character at a specified position in the string
TrimLeft() Removes leading white space characters from a string
TrimRight() Removes trailing white space characters from a string

Besides the functions listed in the table, the CString class also defines a full set of operators for dealing with strings. Using these operators, you can do things like concatenate (join together) strings with the plus sign (+), assign values to a string object with the equal sign (=), access the string as a C-style string with the LPCTSTR operator, and more.

Creating a string object is quick and easy, like this:

CString str = "This is a test string";

Of course, there are lots of ways to construct your string object. The previous example is only one possibility. You can create an empty string object and assign characters to it later; you can create a string object from an existing string object; and you can even create a string from a repeating character. The CString class's many overloaded constructors look like this:

CString( )
CString( const CString& stringSrc )
CString( TCHAR ch, int nRepeat = 1 )
CString( LPCTSTR lpch, int nLength )
CString( const unsigned char* psz )
CString( LPCWSTR lpsz )
CString( LPCSTR lpsz )  

After you have the string object created, you can call its member functions and so manipulate the string in a number of ways. For example, to convert all of the characters in the string to uppercase, you'd make a function call like this:

str.MakeUpper();

Or, to compare two strings, you'd make a function call something like this:

str.Compare("Test String");

You can also compare two CString objects:

CString testStr = "Test String";
str.Compare(testStr);

If you peruse your online documentation, you'll find that most of the other CString member functions are equally easy to use as those described here.

The CTime and CTimeSpan Classes

If you've ever tried to manipulate time values returned from a computer, you'll be pleased to learn about MFC's CTime and CTimeSpan classes, which represent absolute times and elapsed times, respectively. Table 19.3 lists the member functions of the CTime class, and Table 19.4 lists the member functions of the CTimeSpan class.

Table 19.3 Member Functions of the CTime Class

Function Description
Format() Constructs a string representing the time object's time.
FormatGmt() Constructs a string representing the time object's GMT (or UTC) time. This is the Greenwich mean time.
GetCurrentTime() Creates a CTime object for the current time.
GetDay() Gets the time object's day as an integer.
GetDayOfWeek() Gets the time object's day of the week, starting with 1 for Sunday.
GetGmtTm() Gets a time object's second, minute, hour, day, month, year, day of the week, and day of the year as a tm structure.
GetHour() Gets the time object's hour as an integer.
GetLocalTm() Gets a time object's local time, returning the second, minute, hour, day, month, year, day of the week, and day of the year in a tm structure.
GetMinute() Gets the time object's minutes as an integer.
GetMonth() Gets the time object's month as an integer.
GetSecond() Gets the time object's second as an integer.
GetTime() Gets the time object's time as a time_t value.
GetYear() Gets the time object's year as an integer.

Table 19.4 Member Functions of the CTimeSpan Class

Function Description
Format() Constructs a string representing the time-span object's time
GetDays() Gets the time-span object's days
GetHours() Gets the time-span object's hours for the current day
GetMinutes() Gets the time-span object's minutes for the current hour
GetSeconds() Gets the time-span object's seconds for the current minute
GetTotalHours() Gets the time-span objects total hours
GetTotalMinutes() Gets the time-span object's total minutes
GetTotalSeconds() Gets the time-span object's total seconds

Using a CTime Object

Creating a CTime object for the current time is a simple matter of calling the GetCurrentTime() function, like this:

CTime time = CTime::GetCurrentTime();

Notice that, because GetCurrentTime() is a static member function of the CTime class, you can call it without actually creating a CTime object. You do, however, have to include the class's name as part of the function call, as shown in the preceding code. As you can see, the function returns a CTime object. This object represents the current time. If you wanted to display this time, you could call upon the Format() member function, like this:

CString str = time.Format("DATE: %A, %B %d, %Y");

The Format() function takes as its single argument a format string that tells the function how to create the string representing the time. The previous example creates a string that looks something like this:

DATE: Saturday, April 20, 1996

The format string used with Format() is not unlike the format string that you use with functions like the old DOS favorite, printf() or the Windows conversion function, wsprintf(). That is, you specify the string's format by including literal characters along with control characters. The literal characters, such as "DATE:" and the commas in the previous string example, are added to the string exactly as you type them, whereas the format codes are replaced with the appropriate values. For example, the %A in the previous code example will be replaced by the name of the day, and the %B will be replaced by the name of the month.

Although the format-string concept is the same as that used with printf(), the Format() function has its own set of format codes, which are listed in Table 19.5.

Table 19.5 Format Codes for the Format() Function

Code Description
%a Day name, abbreviated (such as Sat for Saturday)
%A Day name, no abbreviation
%b Month name, abbreviated (such as Mar for March)
%B Month name, no abbreviation
%c Localized date and time (for the U.S., that would be something like 03/17/96 12:15:34)
%d Day of the month as a number (01[nd]31)
%H Hour in the 24-hour format (00[nd]23)
%I Hour in the normal 12-hour format (01[nd]12)
%j Day of the year as a number (001[nd]366)
%m Month as a number (01[nd]12)
%M Minute as a number (00[nd]59)
%p Localized a.m./p.m. indicator for 12-hour clock
%S Second as a number (00[nd]59)
%U Week of the year as a number (00[nd]51, considering Sunday to be the first day of the week)
%w Day of the week as a number (0[nd]6, with Sunday being 0)
%W Week of the year as a number (00[nd]51, considering Monday to be the first day of the week)
%x Localized date representation
%X Localized time representation
%y Year without the century prefix as a number (00[nd]99)
%Y Year with the century prefix as a decimal number (such as 1996)
%z Name of time zone, abbreviated
%Z Name of time zone, no abbreviation
%% Percent sign

Other CTime member functions like GetMinute(), GetYear(), and GetMonth() are obvious in their usage. However, you might like an example of using a function like GetLocalTm():

struct tm* timeStruct;
timeStruct = time.GetLocalTm();

The first line of the previous code declares a pointer to a tm structure. (The tm structure is defined by Visual C++.) The second line sets the pointer to the tm structure created by the call to GetLocalTm(). Essentially, this function call retrieves all of the time information at once, organized in the tm structure, which is defined in the header file TIME.H, as shown in Listing 19.1.

Listing 19.1[em]LST19_01.cpp[md]The tm Structure

struct tm {
        int tm_sec;     /* seconds after the minute - [0,59] */
        int tm_min;     /* minutes after the hour - [0,59] */
        int tm_hour;    /* hours since midnight - [0,23] */
        int tm_mday;    /* day of the month - [1,31] */
        int tm_mon;     /* months since January - [0,11] */
        int tm_year;    /* years since 1900 */
        int tm_wday;    /* days since Sunday - [0,6] */
        int tm_yday;    /* days since January 1 - [0,365] */
        int tm_isdst;   /* daylight savings time flag */
        };

The CTime class features a number of overloaded constructors, enabling you to create CTime objects in various ways and using various times.

Using a CTimeSpan Object

A CTimeSpan object is nothing more complex than the difference between two times. You can use CTime objects in conjunction with CTimeSpan objects to easily determine the amount of time that's elapsed between two absolute times. To do this, first create a CTime object for the current time. Then, when the time you're measuring has elapsed, create a second CTime object for the current time. Subtracting the old time object from the new one gives you a CTimeSpan object representing the amount of time that has elapsed. The example in Listing 19.2 shows how this process works.

Listing 19.2[em]LST19_02.cpp[md]Calculating a Time Span

CTime startTime = CTime::GetCurrentTime();
    //.
    //. Time elapses...
    //.
CTime endTime = CTime::GetCurrentTime();
CTimeSpan timeSpan = endTime - startTime;

The CPoint Class

In many applications, you need to deal with locations of various types. For example, when a user clicks the mouse, the system records the location of the mouse pointer. Moreover, many graphics-drawing functions use screen locations. As you know, a location on the screen is represented by an X,Y coordinate. In order to simplify handling such coordinates, MFC provides the CPoint class, which is a kind of wrapper around Windows' POINT structure.

You create a CPoint object by calling its constructor. Because the constructor is overloaded in the class, you can construct a CPoint object using various types of arguments. The many CPoint constructors look like this:

CPoint( );
CPoint( int initX, int initY );
CPoint( POINT initPt );
CPoint( SIZE initSize );
CPoint( DWORD dwPoint );

The first constructor creates an uninitialized CPoint object. The other constructors create the object from two integers, from a POINT structure, from a SIZE structure, or from a double word in which the low word contains the X coordinate and the high word contains the Y coordinate.

After you've created the CPoint object, you can manipulate it using the class's member function and operators. The class has only a single member function called Offset(), which enables you to add or subtract from the point. This function is overloaded in the class, enabling you to supply various types of arguments, as follows:

void Offset( int xOffset, int yOffset );
void Offset( POINT point );
void Offset( SIZE size );

The CPoint class also features a set of operators for manipulating the object, including +, -, +=, ==, and !=.

The class's two data members are x and y, which, of course, hold the X and Y coordinates of the point.

The CSize Class

In your previous Windows programming, you've probably come across SIZE structures, which hold the width and height of a rectangle. MFC encapsulates this data structure into its CSize class.

You create a CSize object by calling its constructor. Because the constructor is overloaded in the class, you can construct a CSize object using various types of arguments. The various CSize constructors look like this:

CSize( );
CSize( int initCX, int initCY );
CSize( SIZE initSize );
CSize( POINT initPt );
CSize( DWORD dwSize );

The first constructor creates an uninitialized CSize object. The other constructors create the object from two integers, from a SIZE structure, from a POINT structure, or from a double word in which the low word contains the rectangle's width, and the high word contains the rectangle's height.

After you've created the CSize object, you can manipulate it using the class's operators, which include +, -, +=, -=, ==, and !=. The class's two data members are cx and cy, which hold the width and height of the rectangle.

The CRect Class

Rectangles are everywhere in Windows programming. Although the CSize class enables you to specify the width and height of a rectangle, the class doesn't hold a rectangle's position. To fully specify a rectangle including its position and size you need an object of MFC's CRect class, which encapsulates Windows' RECT structure.

You create a CRect object by calling its constructor. Because, like the CPoint and CSize classes, the constructor is overloaded in the class, you can construct a CRect object, using various types of arguments. The CRect constructors look like this:

CRect( );
CRect( int l, int t, int r, int b );
CRect( const RECT& srcRect );
CRect( LPCRECT lpSrcRect );
CRect( POINT point, SIZE size );
CRect( POINT topLeft, POINT bottomRight );

The first constructor creates an uninitialized CRect object. The other constructors create the object from the following:

After creating the CRect object, you can manipulate it using the class's member functions and operators. The class's member functions are listed in Table 19.6 along with their descriptions.

Table T.6 Member Functions of the CRect Class

Function Description
BottomRight() Gets the rectangle's bottom-right point
CenterPoint() Gets the rectangle's center point
CopyRect() Copies a rectangle's position and size to the rectangle object
DeflateRect() Reduces a rectangle's width and height
EqualRect() Returns TRUE if the given rectangle is equal to the rectangle object
Height() Gets the rectangle's height
InflateRect() Increases the rectangle's width and height
IntersectRect() Sets the rectangle equal to the intersection of two rectangles
IsRectEmpty() Returns TRUE if the rectangle's width or height is 0
IsRectNull() Returns TRUE if the rectangle's top, bottom, left, and right data members are 0
NormalizeRect() Normalizes the rectangle's width and height
OffsetRect() Repositions the rectangle
PtInRect() Returns TRUE if the given point lies within the rectangle
SetRect() Sets the rectangle's position and size
SetRectEmpty() Sets all of the rectangle's data members to 0
Size() Returns the rectangle's size
SubtractRect() Subtracts one rectangle from another
TopLeft() Gets the rectangle's top-left point
UnionRect() Sets the rectangle equal to the union of two rectangles
Width() Gets the rectangle's width

The CRect class's four data members are top, bottom, left, and right, which hold the locations of the rectangle's top, bottom, left, and right edges.

The CRect class also features a set of operators for manipulating the object, including +, -, +=, ==, !=, &=, |=, &, and |. In addition, the LPRECT and LPCRECT operators cast the CRect object to a RECT pointer or to a CRect pointer, respectively.