GridCtrl 控件FAQ

清泛编译

目录

1. 一个固定用法... 1

2. 可以控制单元格是否可以编辑... 3

3. 在选定一个单元格时,选择整行... 3

4. 说明添加固定列头和固定行头的方法... 3

5. 说明填写表格内容的方法... 5

6. 在选定一行时有响应函数... 6

7. 由双击的响应函数... 6

8. 由响应右键点击的函数... 6

9. 可以方便的删除和添加固定列头... 7

10.可以设置、删除、添加固定行头... 7

11.可以在第一个单元格中加入Check控件... 8

12.可设表格的背景和字体,可设单元格的颜色和字体... 8

13.可以方便的添加或者删除一行... 9

14.可以由程序选定某一行... 9

15.可以由程序自动滚动到某一行,显示在用户面前... 10

16.说明添加排序功能的方法... 10

17.说明在单元格中添加或者改变图形的方法... 11

18.遍历所有的选中行的方法... 11

19.设置控件允许单选或者多选的方法... 13

20.设置不要焦点和焦点外框的方法... 13

21.CGridCtrl的扩展... 13

 

 

1. 一个固定用法

一个常用的用法是将CridCtrl当做ListCtrl那样的用,同时又增加了即时编辑的功能:

以下假设在一个Dlg增加一个GridCtrl的控件:

我们可以按以下步骤进行:

第一步:表格控件加到工程中去

可以有两种方法:

(1)可以使用controls panel中的custom control添加,添加后如下设置:

(2)也可以用菜单ViewResource Symbol添加一个ID号(适用于Create出来的GridCtrl

第二步:在Dlg的头文件中加入

       CGridCtrl  m_Grid;

第三步:Create控件(如果是controls panel中的custom control添加的可以跳过)

DlgOnCreate函数中添加

m_Grid.Create(……)代码

第四步:创始化控件

DoDataExchange中添加

DDX_GridControl(pDX, IDC_GRID, m_Grid);

DlgOnInitialDialog中添加如下代码:

//设置控件类似于ListCtrl的表现

m_Grid.SetListMode(TRUE);

 

//设置控件的初始行数和列数

m_Grid.SetRowCount(1);

m_Grid.SetColumnCount(4);

 

//设置控件背景颜色,这里GetDefaultCell的两个参数分别表示是否是固定行或者是固定列。如果不设定,缺省的颜色为白色。

m_Grid.GetDefaultCell(FALSE, FALSE)->SetBackClr(Color);

//设置控件的固定行为一行,一般是必须的

m_Grid.SetFixedRowCount(1);

//设置控件的固定列为一列,

m_Grid.SetFixedColumnCount(1); //第一列为固定列一列

//设置控件的固定行或者固定列不能被选中(默认就是固定的不能被选)

m_Grid.SetFixedColumnSelection(FALSE);

m_Grid.SetFixedRowSelection(FALSE);

 

//设置控件是否允许隐藏行或者列

m_Grid.EnableColumnHide(FALSE);

m_Grid.EnableRowHide(FALSE);

 

//设置控件是否允许编辑

m_Grid.SetEditable(FALSE);

 

//设置控件是否允许选择

m_Grid.EnableSelection(TRUE);

 

 

//设置控件是否允许点击表头排序

m_Grid.SetHeaderSort(TRUE);

//设置控件是否允许多选或者单选

m_Grid.SetSingleRowSelection(TRUE);   

m_Grid.SetSingleColSelection(TRUE);

 

//设置控件是否允许自动调整行列大小

m_Grid.SetRowResize(FALSE);

m_Grid.SetColumnResize(FALSE);

 

//设置控件不要焦点和焦点外框

    m_Grid.SetTrackFocusCell(FALSE);

    m_Grid.SetFrameFocusCell(FALSE);

 

第五步:设置控件的内容

强烈建议添加以下Dlg的两个成员函数:

void FillColumn();   //具体内容见4

void FillItem();     //具体内容见5

第六步:设置控件的响应

具体可见678

其它

在使用过程中经常需要由程式设定选中行,请始终连续使用以下两个语句:

m_Grid.SetSelectedRange(nRow,0, nRow,m_Grid.GetColumnCount()-1)

m_Grid.EnsureVisible(nRow, 0);

其中nRow为要选中的那一行,强烈建议不要将这两句语句放在FillItem()中,这样会导致不灵活。

 

 

2. 可以控制单元格是否可以编辑

l  可以设定整张表格为只读

void CGridCtrl::SetEditable(BOOL bEditable = TRUE)

参数设为FALSE,则整张表格为只读。

l  也可以设定某个单元格为只读

BOOL CGridCtrl::SetItemState(int nRow, int nCol, UINT state)

一般需配合使用UINT CGridCtrl::GetItemState(int nRow, int nCol) const

比如将单元格(11)设为只读

CGridCtrlObject.SetItemState(1,1, m_Grid.GetItemState(1,1) | GVIS_READONLY);

将单元格(11)设为正常

CGridCtrlObject.SetItemState(1,1, m_Grid.GetItemState(1,1) & ~GVIS_READONLY);

单元格可用的状态常量

            &nnbsp;   GVIS_FOCUSED      // Cell has focus

                   GVIS_SELECTED     // Cell is selected

                   GVIS_DROPHILITED  // Cell is drop highlighted

                   GVIS_READONLY    // Cell is read-only and cannot be edited

                   GVIS_FIXED         // Cell is fixed

                   GVIS_FIXEDROW     // Cell is part of a fixed row

                   GVIS_FIXEDCOL     // Cell is part of a fixed column

                   GVIS_MODIFIED     // Cell has been modified

 

 

3. 在选定一个单元格时,选择整行

void CGridCtrl::SetListMode(BOOL bEnableListMode = TRUE)

先设定表格为ListMode

 

 

4. 说明添加固定列头和固定行头的方法

         CGridCtrlObject.SetFixedColumnCount(NumberFixCol);

         CGridCtrlObject.SetFixedRowCount(NumberFixRow);

        

         CGridCtrlObject.SetFixedColumnSelection(FALSE);

CGridCtrlObject.SetFixedRowSelection(FALSE);

 

添加固定表头的方法如下:

    m_Grid.SetFixedRowCount(1);     //设定固定行数为1

 

    const int nColumnNum=3;

    m_Grid.SetColumnCount(nColumnNum);

    int nWidth[nColumnNum];

    nWidth[0]=60;

    nWidth[1]=120;

    nWidth[2]=120;

 

    for(int i=0; i<m_ nColumnNum; i++)

       m_Grid.SetColumnWidth(i, nWidth[i]);

    i=0;

    m_Grid.SetItemText(0,i++,"第一列");

    m_Grid.SetItemText(0,i++,"第二列");

    m_Grid.SetItemText(0,i++,"第三列");

 

5. 说明填写表格内容的方法

l  简单的方法是调用

BOOL CGridCtrl::SetItemText(int nRow, int nCol, LPCTSTR str)

例如CGridCtrlObject.SetItemText(1,1, _T("12345"));

l  复杂但更灵活的方法是采用如下的方法:

         GV_ITEM Item;//一个结构

         设定这个结构的成员参数,然后将这个结构传递给表格,

         CGridCtrlObject.SetItem(&Item);

:

typedef struct _GV_ITEM {
        int      row,col;   // Row and Column of item
        UINT     mask;      // Mask for use in getting/setting cell data
        UINT     state;     // cell state (focus/hilighted etc)
        UINT     nFormat;   // Format of cell. Default imaplentation 
                            // used CDC::DrawText formats
        CString  szText;    // Text in cell
        int      iImage;    // index of the list view item’s icon
        COLORREF crBkClr;   // Background colour (or CLR_DEFAULT)
        COLORREF crFgClr;   // Forground colour (or CLR_DEFAULT)
        LPARAM   lParam;    // 32-bit value to associate with item
        LOGFONT  lfFont;    // cell font

} GV_ITEM;

例如以下代码可以设置表格内容:

    m_GridCtrl.SetRowCount(3);

    m_GridCtrl.SetItemText(1, 0, "第一格");

    m_GridCtrl.SetItemText(1, 1, "第二格");

    m_GridCtrl.SetItemText(1, 2, "第三格");

    m_GridCtrl.SetItemText(2, 0, "第四格");

    m_GridCtrl.SetItemText(2, 1, "第五格");

    m_GridCtrl.SetItemText(2, 2, "第六格");

 

    m_GridCtrl.ExpandColumnsToFit();

 

6. 在选定一行时有响应函数

7. 由双击的响应函数

8. 由响应右键点击的函数

A

当进行单击,双击或右击单元格等操作时,表格会发送响应的消息,可以在父窗口添加处理消息的函数,做法如下:

GVN_BEGINDRAG      // Sent when dragging starts
GVN_BEGINLABELEDIT // Sent when inplace editing starts
GVN_ENDLABELEDIT   // Sent when inplace editing stops
GVN_SELCHANGING    // Sent just before cell selection changes
GVN_SELCHANGED     // Sent after cell selection changes
GVN_GETDISPINFO    // A request for cell information when the grid is 
                   // in virtual mode
GVN_ODCACHEHINT    // Cache hint when in virtual mode

右键点击,按键盘响应消息在扩展中实现了,可参见条款21

以下需要手工添加

H文件中:

         // Generated message map functions

         //{{AFX_MSG(CDlgSectionLib)

 

         //}}AFX_MSG

         afx_msg void OnGridDblClick(NMHDR *pNotifyStruct, LRESULT* pResult);

         afx_msg void OnGridClick(NMHDR *pNotifyStruct, LRESULT* pResult);

    afx_msg void OnGridEndSelChange(NMHDR *pNotifyStruct, LRESULT* pResult);

         DECLARE_MESSAGE_MAP()

CPP文件中:

BEGIN_MESSAGE_MAP(CDlgSectionLib, CDialog)

         //{{AFX_MSG_MAP(CDlgSectionLib)

         //}}AFX_MSG_MAP

        

         ON_NOTIFY(NM_DBLCLK, IDC_GRID, OnGridDblClick)

         ON_NOTIFY(NM_CLICK, IDC_GRID, OnGridClick)

         ON_NOTIFY(GVN_SELCHANGED, IDC_GRID, OnGridEndSelChange)

 

END_MESSAGE_MAP()

然后自定义响应函数

void CDlgSectionLib::OnGridDblClick(NMHDR *pNotifyStruct, LRESULT* pResult)

{

NM_GRIDVIEW* pItem = (NM_GRIDVIEW*) pNotifyStruct;

pItem->iRow, pItem->iColumn//得到当前行、列

}

 

// This structure sent to Grid's parent in a WM_NOTIFY message

typedef struct tagNM_GRIDVIEW {

    NMHDR hdr;

    int   iRow;

    int   iColumn;

} NM_GRIDVIEW;

 

typedef struct tagNMHDR {
HWND hwndFrom;  // handle of control sending message
UINT idFrom;// identifier of control sending message
UINT code;  // notification code; see below
} NMHDR;
 
NM_CLICK   The user has clicked the left mouse button within the control. 
NM_DBLCLK   The user has double-clicked the left mouse button within the control. 
NM_KILLFOCUS   The control has lost the input focus. 
NM_OUTOFMEMORY   The control could not complete an operation because there is not enough memory available. 
NM_RCLICK   The user has clicked the right mouse button within the control. 
NM_RDBLCLK   The user has double-clicked the right mouse button within the control. 
NM_RETURN   The control has the input focus, and the user has pressed the ENTER key. 
NM_SETFOCUS   The control has received the input focus. 

 

 

9. 可以方便的删除和添加固定列头

10.可以设置、删除、添加固定行头

A

参考(4)&(5)

删除可以用以下一些函数

    BOOL DeleteColumn(int nColumn);

    BOOL DeleteRow(int nRow);

    BOOL DeleteNonFixedRows();

    BOOL DeleteAllItems();

 

 

11.可以在第一个单元格中加入Check控件

A

       #include "NewCellTypes/GridCellCheck.h"//包含头文件

 

         BOOL CGridCtrl::SetCellType(int nRow, int nCol, CRuntimeClass* pRuntimeClass);

 

比如:CGridCtrlObject.SetCellType(1,1, RUNTIME_CLASS(CGridCellCheck));

 

 

12.可设表格的背景和字体,可设单元格的颜色和字体

设置表格的颜色CGridCtrlObject.GetDefaultCell(FALSE, ALSE)->SetBackClr(RGB(xxx,xxx,xxx));

下面的函数均可以调用:

virtual void CGridCtrl::SetTextClr(COLORREF clr);
virtual void CGridCtrl::SetBackClr(COLORREF clr);
virtual void CGridCtrl::SetFont(const LOGFONT* plf);

 

设置单元格的背景颜色和前景颜色

 

BOOL CGridCtrl::SetItemBkColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT)

BOOL CGridCtrl::SetItemFgColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT)

BOOL CGridCtrl::SetItemFont(int nRow, int nCol, LOGFONT*lf)

 

颜色:

COLORREF clr = RGB(xxx,xxx,xxx);

 

字体:

CFont* pFont = m_Grid.GetFont();

LOGFONT lf;

pFont->GetLogFont(&lf);

memcpy(lf.lfFaceName, _T("Arial"), 6);

lf.lfEscapement = 900;

lf.lfOrientation = 900;

 

关于单元格的格式都可以通过下述方法设定,同前面关于设置单元格内容(4)的方法

GV_ITEM Item

设置单元格格式

Item.crBkClr = ;  

Item.crFgClr = ;                

Item.mask    |= (GVIF_BKCLR|GVIF_FGCLR);

Item.lfFont=;

SetItem(&Item);

 

 

13.可以方便的添加或者删除一行

int CGridCtrl::InsertColumn(LPCTSTR strHeading,UINT nFormat, int nColumn = -1)

int CGridCtrl::InsertRow(LPCTSTR strHeading, int nRow = -1)

BOOL DeleteColumn(int nColumn)

BOOL DeleteRow(int nRow)

例如:

CGridCtrlObject.InsertRow(_T("Newest Row"), nRow);

CGridCtrlObject.DeleteRow(nRow);

CGridCtrlObject.Invalidate();//这句是必需的。

 

 

14.可以由程序选定某一行

可以调用以下函数:

void SelectRow (int row)     //该函数在扩展中实现了,具体可参见条款21

也可以调用以下函数:

void SetSelectedRange(const CCellRange& Range, BOOL bForceRepaint = FALSE);

void SetSelectedRange(int nMinRow, int nMinCol, int nMaxRow, int nMaxCol, BOOL bForceRepaint = FALSE);

CCellID SetFocusCell(CCellID cell);
CCellID SetFocusCell(int nRow, int nCol);

 

class CCellID
{    
public:
    int row, col; // The zero based row and column of the cell.
 
    CCellID(int nRow = -1, int nCol = -1)
 
    int IsValid();
    int operator==(const CCellID& rhs);
    int operator!=(const CCellID& rhs);
}

 

也可以调用BOOL CGridCtrl::SetRowFocusAndSelection(int nRow,int nCol=0)

这个函数选中第nRow行,同时将焦点置于第nRow0,第nCol列。成功则返回TRUE,失败则返回FALSE.

 

 

15.可以由程序自动滚动到某一行,显示在用户面前

调用void CGridCtrl::AutoScrollToRow(int nRow)

也可以使用

void EnsureVisible(CCellID &cell)

   void EnsureVisible(int nRow, int nCol);

 

 

16.说明添加排序功能的方法

调用如下函数:

void CGridCtrl::SetListMode(BOOL bEnableListMode = TRUE)

void CGridCtrl::SetHeaderSort(BOOL bSortOnClick = TRUE)

void CGridCtrl::SetCompareFunction(PFNLVCOMPARE pfnCompare)

如果想实现排序,必须先调用

CGridCtrlObject.SetListMode(TRUE);

CGridCtrlObject.SetHeaderSort(TRUE);

然后设置比较函数:

CGridCtrlObject.SetCompareFunction(CGridCtrl::pfnCellNumericCompare);//数值排序

CGridCtrlObject.SetCompareFunction(CGridCtrl:: pfnCellTextCompare);//字符排序

CGridCtrlObject.SetCompareFunction(NULL);//调用缺省的排序模式,即字符排序

字符排序和数值排序是控件已提供的排序模式,也可以自定义排序函数,例子如下:

int CALLBACK pfnCellCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
比较函数必须是全局的或是静态的。
int CALLBACK MyClass::pfnCellNumericCompare(LPARAM lParam1,
                                            LPARAM lParam2, 
                                            LPARAM lParamSort)
{
         CGridCellBase* pCell1 = (CGridCellBase*) lParam1;
         CGridCellBase* pCell2 = (CGridCellBase*) lParam2;
         if (!pCell1 || !pCell2) return 0;
 
         int nValue1 = _ttol(pCell1->GetText());
         int nValue2 = _ttol(pCell2->GetText());
 
         if (nValue1 < nValue2)
                 return -1;
         else if (nValue1 == nValue2)
                 return 0;
         else
                 return 1;

}

 

 

17.说明在单元格中添加或者改变图形的方法

也可以这样实现

头文件CImageList m_ImageList;

实现文件中

m_ImageList.Create(MAKEINTRESOURCE(BitMapID如:IDB_IMAGES), 16, 1, RGB(255,255,255));

CGridCtrlObject.SetImageList(&m_ImageList);

然后调用

BOOL CGridCtrl::SetItemImage(int nRow, int nCol, int iImage)

也可以采用(4)中设置单元格的文字内容的方法:

GV_ITEM Item;

Item.iImage =index;

Item.mask  |= (GVIF_IMAGE);

CGridCtrlObject.SetItem(&Item);

 

 

18.遍历所有的选中行的方法

 

 
GVNI_FOCUSED     // Search for focus cell
GVNI_SELECTED    // Search for selected cells
GVNI_DROPHILITED // Search for drop highlighted cells
GVNI_READONLY    // Search for read-only cells
GVNI_FIXED       // Search for fixed cells 
GVNI_MODIFIED    // Search for modified cells
 
 
GVNI_ABOVE       // Search above initial cell
GVNI_BELOW       // Search below initial cell
GVNI_TOLEFT      // Search to the left of the initial cell
GVNI_TORIGHT     // Search to the right of the initial cell
GVNI_ALL         // Search all cells in the grid starting from
                 // the given cell
GVNI_AREA        // Search all cells below and to the right of 
                 // the given cell

CellID GetNextItem(CCellID& cell, int nFlags) const使用方法参见CListCtrl::GetNextItemMSDN

下面两个函数也值得注意:

BOOL IsCellSelected(CCellID &cell) const

BOOL IsCellSelected(CCellID cell) const

 

因为遍历同时要进行的具体操作不尽相同,所以我们要在使用时结合GetNextItem函数自己设计函数,这样就可以实现遍历操作了。

 

推荐使用以下用法:

int sel=m_Grid.GetNextRow(-1, GVNI_SELECTED);

while(sel!=-1)

{

    //做一些事情

    sel=m_Grid.GetNextRow(sel, 2);

    //那个GVNI_SELECTED的值是2,其中GetNextRow是扩展定义的函数,见21

}

 

我们也可以设计一个函数,对所有单元便历,找到选中的单元

        

std::list<CCellID> BeSelectedList;

for(int i=0;i<GetRowCount();i++){

                  for(int j=0;j<GetColumnCount();j++){

                            CCellID unit(i,j);

                            if(IsCellSelected(unit))

                                     BeSelectedList.push_back(unit);

                  }

}

 

 

19.设置控件允许单选或者多选的方法

    m_Grid. SendMessageToParent (TRUE);   

    m_Grid.SetSingleColSelection(TRUE);

 

 

20.设置不要焦点和焦点外框的方法

    m_Grid.SetTrackFocusCell(FALSE);

    m_Grid.SetFrameFocusCell(FALSE);

 

 

21.CGridCtrl的扩展

为了方便使用,我们对CGridCtrl控件进行了扩展,涉及到以下一些方面:

l  添加了void CGridCtrl::SelectRow(int row)函数,可以方面的选中一行。

l  添加了int CGridCtrl::GetNextRow(int nRow, int nFlags) const函数,可以快速的找到选中行、有焦点的行等等。

l  添加了LRESULT CGridCtrl::SendKeyMessage(WORD wVKey, UINT flags) const函数,用于向父窗口发送键盘消息,在父窗口中用ON_NOTIFY(WM_KEYDOWN, <id>, <响应函数>) 即可接受。

l  扩展了SendMessageToParent函数,在向父窗口发送的信息中携带了鼠标位置信息。

l  添加了向父窗口发送鼠标右键点击消息。

l  添加了向父窗口发送点击表头的信息(原来只定义了常量,没有发送该消息)。
 


选中一行可以使用下面的方法:

//选中单元格
m_Grid.SetItemState(row, col, LVIS_SELECTED | LVIS_FOCUSED);

//取消选中单元格
m_Grid.SetItemState(row, col, LVIS_OVERLAYMASK);

GridCtrl CGridCtrl 控件

分享到:
评论加载中,请稍后...
创APP如搭积木 - 创意无限,梦想即时!
回到顶部