C++5.0下CGridCtrl类的建立与应用

摘要   本文较为详细地介绍了CGridCtrl类的建立,并利用该类实现了在一单文档界面上

       对一数据库内容的显示、修改、添加、删除及打印等功能。

关键词  CGridCtrl类,电子表格,数据库

 一、前言

      在数据库的操作系统中,经常要遇到对数据库的内容进行显示、修改、添加和删除等功能,而一般情况下数据库的容量都是很大的,为此我们通常选用以电子表格的形式来显示数据库的内容,并在其上完成对数据库的修改、添加和删除,使对数据库的操作既直观又方便;如用VB5.0DB 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]类、CInplaceList[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,255));

       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_ELLIPSIS;

                            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+(row-1)*9));

                            }                                                            

              //以下为col==4,5,6,7,8,9时的填写,情况与以上相类似,在此省略。

                            else if(col==10)

                            {                  

                                   Item.szText.Format(_T("%d"),*(Iarray+8+(row-1)*9));

                            }

                else

                {

                 }          

                     }

                            m_Grid.SetItem(&Item);                    //将输入信息填入表格

       if (col == (m_Grid.GetFixedColumnCount()-1) && row >= m_Grid.GetFixedRowCount())

                            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]类的OnEndEditCell()函数来实现,该函数的形式如下:

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.0CGridCtrl[1]类建立与应用的一个初步探讨,CGridCtrl[1]类本身是很复杂,其所能实现的功能也是很强大的,除了我们给大家介绍CGridCtrl[1]类几个基本而又常用的函数之外,CGridCtrl[1]类还有很多用于其他方面的功能函数,在此我们不可能给大家一一介绍,我们利用CGridCtrl[1]类这些基本而又常用的函数,实现了对数据库内容的显示、修改、添加、删除及打印等功能,基本上满足了数据库操作人员的需求。

 

  参考文献

1、http://users.aol.com/chinajoe, Written by Chris Maunder.

2、http://users.aol.com/chinajoe,written by Joe Willcoxson.

3、http://users.aol.com/chinajoe,written by Joe Willcoxson.

4、http://users.aol.com/chinajoe, Written by Chris Maunder.

5、http://www.codeguru.com/listview/edit_subitems.shtml, Written by Chris Maunder.

6、http://www.codeguru.com/listview/edit_subitems.shtml, Written by Motty Cohen.