After creating and resizing my windows, I needed a method for reading in and storing the data for the various house listings. In my original samples, I used static arrays filled with dummy information. This technique is great if you never intend to change the information you are displaying. But in a working application, it makes sense to provide for dynamic data changes.
The easiest way to store the data is to save it in a file. I decided to use an ASCII file because it is easy to test and easy to alter. The file contains the following information:
Here's what the ASCII file looks like:
3
Bellevue
Redmond
Seattle
9
100 Berry Lane,Redmond,175000,3,2,Joan Smith,555-1212
523 Apple Road,Redmond,125000,4,2,Ed Jones,555-1111
1212 Peach Street,Redmond,200000,4,3,Mary Wilson,555-2222
22 Daffodil Lane,Bellevue,2500000,4,4,Joan Smith,555-1212
33542 Orchid Road,Bellevue,180000,3,2,Ed Jones,555-1111
64134 Lily Street,Bellevue,250000,4,3,Mary Wilson,555-2222
33 Nicholas Lane,Seattle,350000,3,2,Joan Smith,555-1212
555 Tracy Road,Seattle,140000,3,2,Ed Jones,555-1111
446 Jean Street,Seattle,225000,4,3,Mary Wilson,555-2222
Parsing the file was simply a matter of using sscanf, converting some of the strings to integers, copying the data to my data structure, and updating my file pointer. The data structures I used contained information about the houses, the cities, and the current state of the application. I filled out a CITYINFO structure for each city listed and a HOUSEINFO structure for each house listed. When saving the information to a file, I reversed the procedure. The code on the next page shows what the structures look like.
typedef struct tagCITYINFO
{
char szCity [MAX_CITY]; // city name
int NumHouses; // number of houses listed in this city
HTREEITEM hItem; // handle to tree view item
} CITYINFO;
typedef struct tagHOUSEINFO
{
char szAddress [MAX_ADDRESS]; // address
char szCity [MAX_CITY]; // city
int iPrice; // price
int iBeds; // number of bedrooms
int iBaths; // number of bathrooms
int iImage; // bitmap index for this house
char szAgent [MAX_CITY]; // listing agent
char szNumber [MAX_CITY]; // listing agent's phone number
} HOUSEINFO;
When I ported CHICOAPP to MFC, I stored data in the view class in member variables rather than using the LISTINFO structure:
typedef struct tagCITYINFO
{
CString szCity; // city name
int NumHouses; // number of houses listed in this city
HTREEITEM hItem; // handle to tree view item
} CITYINFO;
typedef struct tagHOUSEINFO
{
CString szAddress;
CString szCity;
int iPrice;
int iBeds;
int iBaths;
int iImage;
CString szAgent;
CString szNumber;
} HOUSEINFO;
class CMfcexpView : public CView
{
protected: // create from serialization only
CMfcexpView ();
DECLARE_DYNCREATE (CMfcexpView);
// Common controls
CToolBarCtrl m_Toolbar; // toolbar
CStatusBarCtrl m_StatusBar; // status bar
CListCtrl m_ListCtl; // list view control
CImageList m_ImageLarge; // large (32-by-32) image list
CImageList m_ImageSmall; // small (16-by-16) image list
CTreeCtrl m_TreeCtl; // tree view control
// Indexes to icons in the tree view image list
int m_idxForSale;
int m_idxSeattle;
int m_idxSeaSel;
int m_idxRedmond;
int m_idxRedSel;
int m_idxBellevue;
int m_idxBellSel;
// Handles to the root, parent, and previous tree view items
HTREEITEM m_hTPrev;
HTREEITEM m_hParent;
HTREEITEM m_hTRoot;
// House listing information
int m_NumCities; // number of cities
int m_NumHouses; // number of houses
int m_iSelected; // index to selected city
int m_iSelHouse; // index to selected house
HOUSEINFO m_rgHouses [MAX_HOUSES];
CITYINFO m_rgCities [MAX_CITIES];
// Pointer to buffer for listing data
char *m_lpBufPtr;
// Current file opened
LPTSTR m_lpstrFile;
§
}
In the MFC version of the sample, I replaced the character arrays that hold textual information with CString instances. This made it very easy to compare strings and get information to and from the dialog boxes. (You'll see this code later in the chapter.) It wasn't so easy, however, to use the C run-time sscanf to get information from the data file. With character arrays (for example, char szAddress [MAX_ADDRESS]), sscanf works perfectly; but when you use CStrings, this function does not work. To get around this, I used a character buffer and copied the string from the character buffer into CStrings.
// Read the house information for each line.
for (count = 0; count < g_Listing.NumHouses; count++)
{
result = sscanf (lpBufPtr,
"%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%s",
rgHouses[count].szAddress,
rgHouses[count].szCity,
szTemp, szBeds, szBaths,
rgHouses[count].szAgent,
rgHouses[count].szNumber);
rgHouses[count].iPrice = atoi (szTemp);
rgHouses[count].iBeds = atoi (szBeds);
rgHouses[count].iBaths = atoi (szBaths);
§
}