VC下CGridCtrl类的建立与应用
徐继友 江泓
摘要 本文较为详细地介绍了CGridCtrl类的建立,并利用该类实现了在一单文档界面
上
对一数据库内容的显示、修改、添加、删除及打印等功能。
关键词 CGridCtrl类,电子表格,数据库
一、前言
在数据库的操作系统中,经常要遇到对数据库的内容进行显示、修改、添加和删
除等功能,而一般情况下数据库的容量都是很大的,为此我们通常选用以电子表格的形
式来显示数据库的内容,并在其上完成对数据库的修改、添加和删除,使对数据库的操
作既直观又方便;如用VB5.0下DB Grid Control来实现以上功能是较为方便的,但由于
VB的通信速度和数据的处理速度较慢,特别对于要处理和显示的数据量较大时,其速度
较慢表现得尤为明显,为此我们选用在VC++5.0下用CGridCtrl[1]类来实现。
二、CGridCtrl类的建立
CGridCtrl[1]类派生于CWnd类,该类主要包含以下八个方面的函数,其函数形式如下:
class CGridCtrl : public CWnd
{
// 1. CGridCtrl类的构造函数
CGridCtrl(int nRows = 0, int nCols = 0, int nFixedRows = 0, int nFixedCols =
0);
BOOL Create(const RECT& rect, CWnd* parent, UINT nID,
DWORD dwStyle = WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VISIBLE);
// 2. 表格行、列数方面的函数
BOOL SetRowCount(int nRows); /设置表的行数
BOOL SetColumnCount(int nCols); //设置表的列数
BOOL SetFixedRowCount(int nFixedRows = 1); //设置表的固定行数
BOOL SetFixedColumnCount(int nFixedCols = 1); //设置表的固定列
数
int GetFixedRowCount() const; // 取表的固定行数
int GetFixedColumnCount() const; //取表的固定列数
……
// 3. 表格尺寸大小方面的函数
BOOL SetRowHeight(int row, int height); //设置表格单元的高度
BOOL SetColumnWidth(int col, int height); //设置表格单元的宽度
int GetRowHeight(int nRow) const; //获取表格单元的高度
int GetColumnWidth(int nCol) const; //获取表格单元的宽度
void AutoSize(); //对表格单元的高度与宽度进行自动设
置
……
// 4. 表格显示与特征方面的函数
void SetImageList(CImageList* pList); //设置列表图标
void SetEditable(BOOL bEditable = TRUE); //设置表格的编辑状
态
BOOL SetColumnType(int nCol, int nType); //设置表格的列状态
……
// 5. 颜色方面的函数
void SetTextColor(COLORREF clr); //设置输入表格的文本颜色
void SetTextBkColor(COLORREF clr); //设置可供输入文本的表格颜色
void SetFixedTextColor(COLORREF clr); //设置输入固定表格的文本颜色
void SetFixedBkColor(COLORREF clr); //设置固定表格颜色
……
// 6. 表格信息函数
BOOL SetItem(const GV_ITEM* pItem); // 向表格中输入信息
BOOL SetItemText(int nRow, int nCol, LPCTSTR str); //向某一单元表格中输入
文本
BOOL SetItemImage(int nRow, int nCol, int iImage); //在某一单元表格中设置
图标
……
// 7. 编辑方面的函数
virtual void OnEditCell(int nRow, int nCol, UINT nChar) //开始对表格进行
编辑
virtual void OnEndEditCell(int nRow, int nCol, CString str) //结束对表格编
辑
……
// 8. 表格打印函数
void Print(); //打印表格
……
}
CGridCtrl[1]类的构造函数形式如下:
CGridCtrl::CGridCtrl(int nRows, int nCols, int nFixedRows, int nFixedCols)
{
m_crWindowText = ::GetSysColor(COLOR_WINDOWTEXT);
m_crWindowColour = ::GetSysColor(COLOR_WINDOW);
m_cr3DFace = ::GetSysColor(COLOR_3DFACE);
m_nRows = 0; //初始电子表格的行数
m_nCols = 0; //初始电子表格的列数
m_nFixedRows = 0; //初始化固定表格的行数
m_nFixedCols = 0; //初始化固定表格的列数
m_bEditable = TRUE; //初始化表格为可编辑状态
……
//初始化设置表格的行列数
SetRowCount(nRows);
SetColumnCount(nCols);
SetFixedRowCount(nFixedRows);
SetFixedColumnCount(nFixedCols);
// 初始化表格的背景颜色及输入表格的文本颜色
SetTextColor(m_crWindowText);
SetTextBkColor(m_crWindowColour);
SetFixedTextColor(m_crWindowText);
SetFixedBkColor(m_cr3DFace);
……
}
对表格中所输入信息属性的描述,是通过定义一结构体函数来实现,该结构体函数形式
如下:
typedef struct _GV_ITEM {
int row,col; // 输入信息的位置
UINT mask; //输入信息的灰度值
UINT state; // 表格单元的状态
UINT nFormat; // 信息的输入形式
CString szText; // 输入表格单元的文本
} GV_ITEM;
将CGridCtrl类与以下类结合起来,即可构造成在其上可进行编辑和修改的电子表格,这
些类分别为:
1.用于单元表格范围的两个类:CCellRange[2]类和CCellID[3]类;
2.单元表格状态属性的类:CGridCell[4]类;
3.对表格进行编辑的两个类:CInplaceEdit[5]类和CInplaceList[6]类;
三、CGridCtrl类的应用
1.CGridCtrl类实现对数据库内容的显示
在我们建立的一单文档界面应用程序(MyGridCtrlTest)之上,加上CGridCtrl[1]类
,再结合CCellRange[2]类、CCellID[3]类、CGridCell[4]类、CInplaceEdit[5]类、CI
nplaceList[6]类以及用于数据库读写的文件,即可在CMyGridCtrlTestView类的OnDraw
()函数将Main.mdb数据库中的工资表以电子表格的形式显示出来,如图1,
图1 在单文档的界面上以电子表格形式对一工资表的显示
在MyGridCtrlTestView.h中,我们将CGridCtrlEx类(该类为CGriCtrl类的派生)嵌入
到CMyGridCtrlTestView类中,其形式如下:
class CMyGridCtrlTestView : public CView
{
class CGridEx : public CGridCtrl
{
// Override this function to fill InPlaceListBoxes
void FillListItems(int nCol, LPARAM cltList);
……
};
public:
CDemo_ui_devstudioDoc* GetDocument();
CGridEx m_Grid;
CSize m_OldSize;
int *Iarray;
CString *Csarray;
CImageList m_ImageList;
……
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
……
protected:
afx_msg void OnGridCtrlDelete(); //对表格进行删除的函数
afx_msg void OnGridCtrlPrint(); //对表格进行打印的函数
……
};
在CMyGridCtrlTestView类的OnDraw()函数中,我们实现对工资表的电子表格显示,
该函数的形式如下:
void CMyGridCtrlTestView ::OnDraw(CDC* pDC)
{
CMyGridCtrlTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
int s,r;
// 建立一显示CGridCtrl类的矩形
RECT rect;
GetClientRect(&rect);
m_OldSize = CSize(rect.right-rect.left, rect.bottom-rect.top);
m_Grid.Create(rect, (CWnd*)this, 111);
// 打开工资表并将工资表的内容读入数组中
……
s:为工资表的行数;
r:为工资表的列数;
申请两个数组空间,用于存放工资表的内容,分别为:
Csarray=new CString[(s+2)*1]; //用于存放姓名
Iarray=new int[(s+2)*9]; //用于存放工资表中的其他项
目
所申请两个数组空间比实际所需的空间要多两行,对于多出的最末两行中,如为字
符串型变量,将以“0”代替,如为整型变量将以0代替,以供操作员在最末的两行实现
对工资表的添加,如图1所示,
//创造列表图标
m_ImageList.Create(MAKEINTRESOURCE(IDB_IMAGES), 16, 1, RGB(255,255,25
5));
m_Grid.SetImageList(&m_ImageList);
//设置表格的属性特征
m_Grid.SetEditable(TRUE); //设置表格为可编辑状态
m_Grid.SetTextBkColor(RGB(0xFF, 0xFF, 0xE0)); //设置表格的背景颜色
//设置表格的行列数
try {
m_Grid.SetRowCount(s+3);
m_Grid.SetColumnCount(r+1);
m_Grid.SetFixedRowCount(1);
m_Grid.SetFixedColumnCount(1);
}
catch (CMemoryException* e)
{
e->ReportError();
e->Delete();
}
// 将工资表的内容填入表格中
for (int row = 0; row < (s+3); row++)
for (int col = 0; col < (r+1); col++)
{
GV_ITEM Item; //输入信息结构体变量的声明
Item.mask = GVIF_TEXT|GVIF_FORMAT; //所输入信息的
灰度
Item.row = row; //输入信息
的行位置
Item.col = col; //输入信
息的列位置
if (row < 1) {
Item.nFormat = DT_LEFT|DT_WORDBREAK; //输入信息
的格式
if (col == 0 ) {
m_Grid.SetColumnType(col, GVET_NOEDIT); //设置表格列为可编辑
状态
Item.szText.Format(_T("不能编辑")); //设置表格
的文本形式
}
else if (col == 1 ) {
m_Grid.SetColumnType(col, GVET_EDITBOX);
Item.szText.Format(_T("姓名"));
}
else if (col == 2 ) {
m_Grid.SetColumnType(col, GVET_EDITBOX);
Item.szText.Format(_T("固定工资"));
}
else if (col == 3 ) {
m_Grid.SetColumnType(col, GVET_LISTBOX); //设置表格列为下拉
可选状态
Item.szText.Format(_T("住房补贴"));
}
//以下均为对表格第一行标题的设定, 情况与以上相类似,在此将col==4,5,6,7,8,9时
略去。
……
else if(col==10){
m_Grid.SetColumnType(col, GVET_EDITBOX);
Item.szText.Format(_T("公积金"));
}
else
{
}
} else if (col < 1) {
Item.nFormat = DT_RIGHT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPS
IS;
Item.szText.Format(_T("行 %d"),row);
} else {
Item.nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS;
if(col==1)
Item.szText.Format(_T("%s"),Csarray[(row-
1)]);
else if(col==2)
{
Item.szText.Format(_T("%d"),*(Iarray+(row
-1)*9));
}
else if(col==3)
{
Item.szText.Format(_T("%d"),*(Iarray+1+(r
ow-1)*9));
}
//以下为col==4,5,6,7,8,9时的填写,情况与以上相类似,在此省略。
else if(col==10)
{
Item.szText.Format(_T("%d"),*(Iarray+8+(r
ow-1)*9));
}
else
{
}
}
m_Grid.SetItem(&Item); //将输
入信息填入表格
if (col == (m_Grid.GetFixedColumnCount()-1) && row >= m_Grid.GetFixed
RowCount())
m_Grid.SetItemImage(row, col, row%2); //将图标
填入表格的第一列中
}
m_Grid.AutoSize(); //对单元表格的高度与宽度进行自动
设置
m_Grid.SetRowHeight(0, 3*m_Grid.GetRowHeight(0)/2); //设置第一行表格
的高度
delete []Csarray;
delete []Iarray;
}
2.表格的编辑、添加与删除
我们可以对表格的内容直接进行编辑,对于表格中的某一项值是固定的几个取值时,我
们以一下拉的方式让操作员选择某一值进行编辑,这样更有利于操作员的操作,如图1的
第四列,该功能的实现是通过CGridCtrlEx类中的 FillListItems()函数来实现,该函数
的形式如下:
void CMyGridCtrlTestView ::CGridEx::FillListItems(int nCol, LPARAM cltList)
{
CListBox* pList = (CListBox*)cltList;
if (nCol == 3)
{
pList->AddString("0");
pList->AddString("20");
pList->AddString("30");
pList->AddString("40");
pList->AddString("50");
pList->AddString("60");
}
}
我们可以在表格的最末两行对工资表的内容进行添加,如图1所示,对表格中的内容进行
修改和添加的结果都将自动地保存在工资表中,这是通过调用CGridCtrl[1]类的OnEndE
ditCell()函数来实现,该函数的形式如下:
void CGridCtrl::OnEndEditCell(int nRow, int nCol, CString str)
{
SetItemText(nRow, nCol, str);
//打开工资表,读取工资表的总行数为 T
……
if(nRow==(T+1)) //所操作表格的行位置数大于工资表的总行数,是对表进行添加
操作
{
//对工资表进行添加操作
}
else if(nRow<=T) //所操作表格的行位置数不大于工资表的总行数,是对表进行编
辑操作
{
//对工资表进行编辑操作
}
else
{
MessageBox(“nRow error!”);
}
}
我们在编辑菜单(Edit)下设置一对表格进行删除的子菜单 “删除(工资表)”,单击
该子菜单,即可弹出一对话框以供操作员输入要删除人的姓名,在确认无误以后,即可
在工资表中将该人的工资信息自动删除,最后将删除后的工资表以电子表格的形式重新
显示出来,该功能的实现是在CMyGridCtrlTestView类中OnGridCtrlDelete()函数来完成
的。
3. 表格的打印
在文件菜单(File)下设置一对表格进行打印的子菜单 “打印(工资表)”,单
击该子菜单,将调用CMyGridCtrlTestView类中OnPrintGridCell()函数,实现对表格的
打印,该函数的形式如下:
void CMyGridCtrlTestView :: OnGridCtrlPrint ()
{
// TODO: Add your command handler code here
m_Grid.Print();
}
四、小结
本篇是对VC++5.0下CGridCtrl[1]类建立与应用的一个初步探讨,CGridCtrl[1]类
本身是很复杂,其所能实现的功能也是很强大的,除了我们给大家介绍CGridCtrl[1]类
几个基本而又常用的函数之外,CGridCtrl[1]类还有很多用于其他方面的功能函数,在
此我们不可能给大家一一介绍,我们利用CGridCtrl[1]类这些基本而又常用的函数,实
现了对数据库内容的显示、修改、添加、删除及打印等功能,基本上满足了数据库操作
人员的需求。