![]() |
MFC Collections: The CArray Class |
An array is a technique of storing similar information of different items in a common variable of one name. Based on this, consider the following list:
This type of list can be created using a CString-based array. Here is an example: void CExoArray1View::OnDraw(CDC* pDC)
{
CExoArray1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CString lstItemsNames[] = { "Women Coat", "Men Jacket", "Teen Jeans",
"Women Bathing Suit", "Children Playground Dress" };
}
The above type of list is referred to as a single-dimensional. To provide more information about items, you can associate a second or even a third list to the first as follows: void CExoArray1View::OnDraw(CDC* pDC)
{
CExoArray1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CString itemsNumbers[] = { "624376", "274952", "497852", "749752", "394085" };
CString lstItemsNames[] = { "Women Coat", "Men Jacket", "Teen Jeans",
"Women Bathing Suit", "Children Playground Dress" };
double itemsPrices[] = { 225.55, 175.75, 24.50, 34.65, 75.05 };
}
To support C++ arrays, the Microsoft Foundation Class Library (MFC) provides the CArray class. The CArray class is part of the collection classes that the MFC is (very) rich of. This class accomplishes two purposes: it provides the same functionality as a C/C++ array but beyond that, it can grow and shrink at will, which is the main limitation of a C/C++ array. |
|
|
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| ID | Value Variable | Variable Type |
| IDC_ITEMNUMBER | m_ItemNumber | CString |
| IDC_ITEMNAME | m_ItemName | CString |
| IDC_ITEMSIZE | m_ItemSize | CString |
| IDC_UNITPRICE | m_UnitPrice | double |
| IDC_RECORDNUMBER | m_RecordNumber | CString |
|
The Object of the Array List |
|
If you plan to create a list of type CArray, you must first decide the type of values the list would be made of. You can use one of the existing C++ data types such as int, short, double, etc. You can also use one of the MFC defined classes. If none of the C++ data types and none of the MFC classes suit you, you can create your own class as you see fit. Because the MSDN document of the CArray covers some of the C++ data types or the MFC objects, we will create our own class. |
|
|

|
Header File: StoreItem.h |
#pragma once
// CStoreItem command target
class CStoreItem
{
public:
CStoreItem();
CStoreItem(CString number, CString name, CString size, double price);
CStoreItem(const CStoreItem &item);
CStoreItem &operator=(const CStoreItem& item);
virtual ~CStoreItem();
private:
CString nbr;
CString nm;
CString sz;
double uprice;
public:
CString CStoreItem::getItemNumber();
void setItemNumber(CString no);
CString getItemName();
void setItemName(CString desc);
CString getItemSize();
void setItemSize(CString s);
double getUnitPrice();
void setUnitPrice(double price);
};
|
| Source File: StoreItem.cpp |
// StoreItem.cpp : implementation file
//
#include "stdafx.h"
#include "DepartmentStore1.h"
#include "StoreItem.h"
// CStoreItem
CStoreItem::CStoreItem()
{
nbr = "";
nm = "";
sz = "";
uprice = 0.00;
}
CStoreItem::CStoreItem(CString number, CString name, CString size, double price)
{
nbr = number;
nm = name;
sz = size;
uprice = price;
}
CStoreItem::CStoreItem(const CStoreItem &item)
{
nbr = item.nbr;
nm = item.nm;
sz = item.sz;
uprice = item.uprice;
}
CStoreItem &CStoreItem::operator=(const CStoreItem& item)
{
nbr = item.nbr;
nm = item.nm;
sz = item.sz;
uprice = item.uprice;
return *this;
}
CStoreItem::~CStoreItem()
{
}
// CStoreItem member functions
CString CStoreItem::getItemNumber()
{
return nbr;
}
void CStoreItem::setItemNumber(CString no)
{
nbr = no;
}
CString CStoreItem::getItemName()
{
return nm;
}
void CStoreItem::setItemName(CString desc)
{
nm = desc;
}
CString CStoreItem::getItemSize()
{
return sz;
}
void CStoreItem::setItemSize(CString s)
{
sz = s;
}
double CStoreItem::getUnitPrice()
{
return uprice;
}
void CStoreItem::setUnitPrice(double price)
{
uprice = price;
}
|
|
Creating an Array List |
|
To create a list based on the CArray class, you must declare its variable using the regular syntax of a double template. After declaring a CArray variable, you should (must) set its initial size. This is done by calling the CArray::SetSize() method. Its syntax is: void SetSize(INT_PTR nNewSize, INT_PTR nGrowBy = -1); The first argument must be a positive number. If you are creating a brand new list, you should set this argument to 0. The second argument specifies how much the list will need to grow when it becomes necessary. It may be good idea to let the compiler take care of this aspect. For this reason, this argument is optional. |
|
|
// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, // but are changed infrequently #pragma once #ifndef VC_EXTRALEAN #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #endif // Modify the following defines if you have to target a platform prior to the ones specified below. // Refer to MSDN for the latest info on corresponding values for different platforms. #ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. #define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. #endif #ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. #define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. #endif #ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. #define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. #endif #ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. #define _WIN32_IE 0x0400 // Change this to the appropriate value to target IE 5.0 or later. #endif #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit // turns off MFC's hiding of some common and often safely ignored warning messages #define _AFX_ALL_WARNINGS #include <afxwin.h> // MFC core and standard components #include <afxext.h> // MFC extensions #include <afxdisp.h> // MFC Automation classes #include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls #ifndef _AFX_NO_AFXCMN_SUPPORT #include <afxcmn.h> // MFC support for Windows Common Controls #endif // _AFX_NO_AFXCMN_SUPPORT #include <afx.h> #include <afxtempl.h> |
// DepartmentStore1Dlg.h : header file
//
#pragma once
#include "StoreItem.h"
// CDepartmentStore1Dlg dialog
class CDepartmentStore1Dlg : public CDialog
{
// Construction
public:
CDepartmentStore1Dlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_DEPARTMENTSTORE1_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
CArray<CStoreItem, CStoreItem&> StoreItems;
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CString m_ItemNumber;
CString m_ItemName;
CString m_ItemSize;
double m_UnitPrice;
CString m_RecordNumber;
afx_msg void OnBnClickedNewitemBtn();
};
|
CDepartmentStore1Dlg::CDepartmentStore1Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CDepartmentStore1Dlg::IDD, pParent)
, m_ItemNumber(_T(""))
, m_ItemName(_T(""))
, m_ItemSize(_T(""))
, m_UnitPrice(0)
, m_RecordNumber(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
this->StoreItems.SetSize(0);
}
|
|
Operations on Arrays |
|
List Emptiness |
When a CArray variable has been declared, its list is primarily empty, until you start adding items as we will see next. At any time, to find out whether the list is empty or not, you can check the returned value of the CArray::IsEmpty() method. Its syntax is: BOOL IsEmpty( ) const; This method allows you to find out if the list already contains at least one member. |
|
|
void CDepartmentStore1Dlg::OnBnClickedFirstBtn()
{
// TODO: Add your control notification handler code here
if( this->StoreItems.IsEmpty() == TRUE )
return;
}
void CDepartmentStore1Dlg::OnBnClickedPreviousBtn()
{
// TODO: Add your control notification handler code here
if( this->StoreItems.IsEmpty() == TRUE )
return;
}
void CDepartmentStore1Dlg::OnBnClickedNextBtn()
{
// TODO: Add your control notification handler code here
if( this->StoreItems.IsEmpty() == TRUE )
return;
}
void CDepartmentStore1Dlg::OnBnClickedLastBtn()
{
// TODO: Add your control notification handler code here
if( this->StoreItems.IsEmpty() == TRUE )
return;
}
|
|
Item Addition to the List |
|
The CArray class provides various options to add an item to its list. The classic technique consists of calling an add-based function. To support this tradition, the CArray class is equipped with the Add() method. Its syntax is: INT_PTR Add(ARG_TYPE newElement); This method expects as argument the value that would be added. The CArray::Add() method is mostly meant to add an item at the end of the list. If the list doesn't yet contain any value, then Add() would create its first item. If the list already contains a few items and you want to insert a new item at a specific position, one of your options would be to call the CArray::SetAt() method. Its syntax is: void SetAt(INT_PTR nIndex, ARG_TYPE newElement); The first argument of this method is the index that the new item will occupy in the list. The second argument is the item that will be added to the list. When a new item is being added to the list, the compiler increases the amount of memory allocated to the list. Sometimes, the amount increased may be more than was necessary. If you want to intervene in releasing any extra memory that is not used, you can call the CArray::FreeExtra() method. Its syntax is: void FreeExtra(); This method can be used to release unused memory that was allocated when the list of items was increased. |
|
|

![]() |
||||||||||||||||||||||||||||||||||||||||||||
|
| ID | Value Variable | Variable Type |
| IDC_ITEMNUMBER | m_ItemNumber | CString |
| IDC_ITEMNAME | m_ItemName | CString |
| IDC_ITEMSIZE | m_ItemSize | CString |
| IDC_UNITPRICE | m_UnitPrice | double |
// NewItemDlg.cpp : implementation file
//
#include "stdafx.h"
#include <ctime>
#include "DepartmentStore1.h"
#include "NewItemDlg.h"
#include ".\newitemdlg.h"
using namespace std;
// CNewItemDlg dialog
IMPLEMENT_DYNAMIC(CNewItemDlg, CDialog)
CNewItemDlg::CNewItemDlg(CWnd* pParent /*=NULL*/)
: CDialog(CNewItemDlg::IDD, pParent)
, m_ItemNumber(_T(""))
, m_ItemName(_T(""))
, m_ItemSize(_T(""))
, m_UnitPrice(_T("0.00"))
{
}
CNewItemDlg::~CNewItemDlg()
{
}
void CNewItemDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_ITEMNUMBER, m_ItemNumber);
DDX_Text(pDX, IDC_ITEMNAME, m_ItemName);
DDX_Text(pDX, IDC_ITEMSIZE, m_ItemSize);
DDX_Text(pDX, IDC_UNITPRICE, m_UnitPrice);
}
BEGIN_MESSAGE_MAP(CNewItemDlg, CDialog)
END_MESSAGE_MAP()
// CNewItemDlg message handlers
BOOL CNewItemDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
srand( (unsigned)time(NULL) );
int digit1 = 1 + rand() % 8;
int digit2 = 1 + rand() % 8;
int digit3 = 1 + rand() % 8;
int digit4 = 1 + rand() % 8;
int digit5 = 1 + rand() % 8;
int digit6 = 1 + rand() % 8;
this->m_ItemNumber.Format("%d%d%d%d%d%d",
digit1, digit2, digit3,
digit4, digit5, digit6);
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
|

void CDepartmentStore1Dlg::OnBnClickedNewitemBtn()
{
// TODO: Add your control notification handler code here
CNewItemDlg dlg;
CString strNbr, strName, strSize;
double price;
if( dlg.DoModal() )
{
strNbr = dlg.m_ItemNumber;
strName = dlg.m_ItemName;
strSize = dlg.m_ItemSize;
price = atof(dlg.m_UnitPrice);
CStoreItem itmNew(strNbr, strName, strSize, price);
this->StoreItems.Add(itmNew);
}
}
|
|
Array Members |
|
Introduction |
|
The members of a CArray list are stored contiguously like the values of a C/C++ array. Each member of a CArray list can be located by its index, which is of type INT_PTR. To know the index of the last member of the list, you can call the CArray::GetUpperBound() method. Its syntax is: INT_PTR GetUpperBound( ) const; This method produces the index of the last member of the array. |
|
|
class CDepartmentStore1Dlg : public CDialog
{
// Construction
public:
CDepartmentStore1Dlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_DEPARTMENTSTORE1_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
CArray<CStoreItem, CStoreItem&> StoreItems;
INT_PTR CurrentPosition;
// Implementation
protected:
. . . No Change
};
|
|
Accessing a Member of the Array |
|
Probably the most regularly performed operation on a list consists of retrieving the values of its members. In C++, you access the member of an array using its index. To perform the same operation, the CArray class provides various options. One way you can locate an item in the list consists of using the square brackets, the same way you would proceed for a C++ array. The square bracket operator was overloaded with the following syntaxes: TYPE& operator[](INT_PTR nIndex); const TYPE& operator[](INT_PTR nIndex) const; As you can see, this operator takes the index of the desired item and returns the value that is stored at that index. Because the list is zero-based like a C++ array, the first item has an index of 0; the second has an index of 1, and so on. |
|
Accessing the Members of an Array |
|
To store all the members of the list in one pointer, you can call the CArray::GetData() method that is overloaded with two versions whose syntaxes are: const TYPE* GetData( ) const; TYPE* GetData( ); This method can help you access all members of the list as one. |
|
The Number of Items in the List |
|
As mentioned already, one of the strengths of the CArray class over the regular C++ array is that its list can grow or shrink at will. This means that, when an item is added to, or inserted into, the list, the number of items in the list increases. To know the number of items in the list, you can call the CArray::GetCount() method: INT_PTR GetCount() const; Since the list is zero-based, the actual number of items is the total - 1. Besides GetCount(), you can call the CArray::GetSize() method to know the size of the list. The syntax of the GetSize() method is: INT_PTR GetSize() const; This method returns the size of the list. Like GetCount(), the GetSize() method returns the total number of items - 1. |
|
|
void CDepartmentStore1Dlg::OnBnClickedNewitemBtn()
{
// TODO: Add your control notification handler code here
CNewItemDlg dlg;
CString strNbr, strName, strSize;
double price;
if( dlg.DoModal() )
{
strNbr = dlg.m_ItemNumber;
strName = dlg.m_ItemName;
strSize = dlg.m_ItemSize;
price = atof(dlg.m_UnitPrice);
CStoreItem itmNew(strNbr, strName, strSize, price);
this->StoreItems.Add(itmNew);
this->StoreItems.FreeExtra();
this->OnBnClickedLastBtn();
}
}
void CDepartmentStore1Dlg::OnBnClickedFirstBtn()
{
// TODO: Add your control notification handler code here
if( this->StoreItems.IsEmpty() == TRUE )
return;
CurrentPosition = 0;
CStoreItem curItem = this->StoreItems[CurrentPosition];
this->m_ItemNumber = curItem.getItemNumber();
this->m_ItemName = curItem.getItemName();
this->m_ItemSize = curItem.getItemSize();
this->m_UnitPrice = curItem.getUnitPrice();
this->m_RecordNumber.Format("%d of %d", CurrentPosition+1, StoreItems.GetCount());
UpdateData(FALSE);
}
void CDepartmentStore1Dlg::OnBnClickedPreviousBtn()
{
// TODO: Add your control notification handler code here
if( this->StoreItems.IsEmpty() == TRUE )
return;
if( CurrentPosition == 0 )
return;
else
{
CurrentPosition--;
CStoreItem curItem = this->StoreItems[CurrentPosition];
this->m_ItemNumber = curItem.getItemNumber();
this->m_ItemName = curItem.getItemName();
this->m_ItemSize = curItem.getItemSize();
this->m_UnitPrice = curItem.getUnitPrice();
this->m_RecordNumber.Format("%d of %d", CurrentPosition+1, StoreItems.GetCount());
}
UpdateData(FALSE);
}
void CDepartmentStore1Dlg::OnBnClickedNextBtn()
{
// TODO: Add your control notification handler code here
if( this->StoreItems.IsEmpty() == TRUE )
return;
if( CurrentPosition == StoreItems.GetUpperBound() )
this->OnBnClickedLastBtn();
else
{
CurrentPosition++;
CStoreItem curItem = this->StoreItems[CurrentPosition];
this->m_ItemNumber = curItem.getItemNumber();
this->m_ItemName = curItem.getItemName();
this->m_ItemSize = curItem.getItemSize();
this->m_UnitPrice = curItem.getUnitPrice();
this->m_RecordNumber.Format("%d of %d", CurrentPosition+1, StoreItems.GetCount());
}
UpdateData(FALSE);
}
void CDepartmentStore1Dlg::OnBnClickedLastBtn()
{
// TODO: Add your control notification handler code here
if( this->StoreItems.IsEmpty() == TRUE )
return;
CurrentPosition = this->StoreItems.GetUpperBound();
CStoreItem curItem = this->StoreItems[CurrentPosition];
this->m_ItemNumber = curItem.getItemNumber();
this->m_ItemName = curItem.getItemName();
this->m_ItemSize = curItem.getItemSize();
this->m_UnitPrice = curItem.getUnitPrice();
this->m_RecordNumber.Format("%d of %d", CurrentPosition+1, StoreItems.GetCount());
UpdateData(FALSE);
}
|
| Item Name | Size | Unit Price |
| Women Cashmere Lined Glove | 8 | 115.95 |
| Men Trendy Jacket | Medium | 45.85 |
| Women Stretch Flare Jeans | Petite | 27.75 |
| Women Belted Sweater | Large | 15.95 |
| Girls Classy Handbag | One Size | 95.95 |
| Women Casual Dress Shoes | 9.5M | 45.95 |
| Boys Hooded Sweatshirt | M (7/8) | 15.95 |
| Girls Velour Dress | 10 | 12.55 |
| Women Lace Desire Panty | Medium | 7.15 |
| Infant Girls Ballerina Dress | 12M | 22.85 |
| Men Classic Pinstripe Suit | 38 | 145.95 |

If your CArray list contains an item you don't need anymore, you can delete it. To delete an item from the list, you can call the RemoveAt() method. Its syntax is: void RemoveAt(INT_PTR nIndex, INT_PTR nCount = 1); The first argument to this method is the index of the item you want to delete from the list. The value of this argument must be between the bounds of the list. If you pass only one argument, only the item at that position would be deleted. If you want to delete more than one item, pass the desired number as the second argument. To delete all items from a CArray list, call its RemoveAll() method. Its syntax is: void RemoveAll( ); When called, this CArray::RemoveAll() method will clear the list of all members. |
|
|

void CDepartmentStore1Dlg::OnBnClickedDeleteBtn()
{
// TODO: Add your control notification handler code here
if( CurrentPosition >= 0 )
{
this->StoreItems.RemoveAt(CurrentPosition);
this->OnBnClickedLastBtn();
}
}
|
|
|
||
| Home | Copyright © 2004-2005 FunctionX, Inc. | |
|
|
||