您的位置:首页 > 其它

MFC控件使用总结——CListCtrl

2012-07-21 18:31 645 查看
CListCtrl介绍

列表控件可以看作是功能增强的ListBox,它提供了四种风格,而且可以同时显示一列的多中属性值。LVS_ICON ,LVS_SMALLICON ,LVS_LIST, LVS_REPORT 这四种风格决定控件的外观,同时只可以选择其中一种,分别对应:大图标显示,小图标显示,列表显示,详细报表显示。

一、常用函数

1.创建

BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

dwStyle 列表控件的风格

LVS_EDITLABELS 结点的显示字符可以被编辑,对于报表风格来讲可编辑的只为第一列。

LVS_SHOWSELALWAYS 在失去焦点时也显示当前选中的结点

LVS_SINGLESEL 同时只能选中列表中一项

2.首先你需要设置列表控件所使用的ImageList,如果你使用大图标显示风格,你就需要以如下形式调用:

CImageList* SetImageList( CImageList* pImageList, LVSIL_NORMAL);

3.如果使用其它三种风格显示而不想显示图标你可以不进行任何设置,否则需要以如下形式调用:

CImageList* SetImageList( CImageList* pImageList, LVSIL_SMALL);

4.插入列

除LVS_REPORT风格外其他三种风格都只需要直接调用InsertItem就可以了,但如果使用报表风格就必须先设置列表控件中的列信息。

int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat , int nWidth, int nSubItem);

iCol:为列的位置,从零开始

lpszColumnHeading:为显示的列名

nFormat:为显示对齐方式

nWidth:为显示宽度

nSubItem:为分配给该列的列索引。

例如:

m_list.InsertColumn(0,"列头1");

m_list.InsertColumn(1,"列头2");

m_list.InsertColumn(2,"列头3");

m_list.InsertColumn(3,"列头4");

5.设置列宽

CRect rect4;

m_list.GetClientRect(rect4); //获得当前客户区信息

m_list.SetColumnWidth(0,rect4.Width()/4); //设置列的宽度。

m_list.SetColumnWidth(1,rect4.Width()/5);

m_list.SetColumnWidth(2,rect4.Width()/5);

m_list.SetColumnWidth(3,rect4.Width()*8/20);

这部分初始化操作,最好放在对话框类的OnInitDialog()函数里,自动初始化。

6.插入行

int InsertItem( int nItem, LPCTSTR lpszItem );

nItem:指明插入位置

lpszItem:为显示字符。

m_list.InsertItem(0,"数据一"); //插入第一个数据,即第0条数据。先插入,然后在修改其他的信息。

m_list.SetItemText(0,1,"数据二"); //修改第0条数据的其他信息。

m_list.SetItemText(0,2,"数据三");

m_list.SetItemText(0,3,"数据四");

7.删除所有行

m_list.DeleteAllItems();

8.设置每列的显示字符

BOOL SetItemText( int nItem, int nSubItem, LPTSTR lpszText );

nItem:为行位置

nSubItem:为列位置

lpszText:为显示字符

9.其它

COLORREF GetTextColor( )/BOOL SetTextColor( COLORREF cr ):用于得到/设置显示的字符颜色。

COLORREF GetTextBkColor( )/BOOL SetTextBkColor( COLORREF cr ):用于得到/设置显示的背景颜色。

void SetItemCount( int iCount ):用于设置添加进列表中项的数量,当要添加的数据量已明确时使用。

BOOL DeleteItem(int nItem):用于删除某一项

BOOL SetBkImage(HBITMAP hbm, BOOL fTile , int xOffsetPercent, int yOffsetPercent):用于设置背景位图。

CString GetItemText( int nItem, int nSubItem ):用于得到某项的显示字符。

下面的代码演示了如何设置多列并插入数据:

m_list.InsertColumn(0,"Col 1",LVCFMT_LEFT,300,0); //设置列

m_list.InsertColumn(1,"Col 2",LVCFMT_LEFT,300,1);

m_list.InsertColumn(2,"Col 3",LVCFMT_LEFT,300,2);

m_list.InsertItem(0,"Item 1_1");//插入行

m_list.SetItemText(0,1,"Item 1_2");//设置该行的不同列的显示字符

m_list.SetItemText(0,2,"Item 1_3")

二、列表控件的消息映射

列表控件的消息映射同样使用ON_NOTIFY宏,形式如同:ON_NOTIFY( wNotifyCode, id, memberFxn ),wNotifyCode为通知代码,id为产生该消息的窗口ID,memberFxn为处理函数,函数的原型如同void OnXXXList(NMHDR* pNMHDR, LRESULT* pResult),其中pNMHDR为一数据结构,在具体使用时需要转换成其他类型的结构。对于列表控件可能取值和对应的数据结构为:

LVN_BEGINLABELEDIT 在开始某项编辑字符时发送,所用结构:

NMLVDISPINFO

LVN_ENDLABELEDIT 在结束某项编辑字符时发送,所用结构:

NMLVDISPINFO

LVN_GETDISPINFO 在需要得到某项信息时发送,(如得到某项的显示字符)所用结构:NMLVDISPINFO

关于ON_NOTIFY有很多内容,将在以后的内容中进行详细讲解。

关于动态提供结点所显示的字符:首先你在项时需要指明lpszItem参数为:

LPSTR_TEXTCALLBACK。在控件显示该结点时会通过发送TVN_GETDISPINFO来取得所需要的字符,在处理该消息时先将参数pNMHDR转换为

LPNMLVDISPINFO,然后填充其中item.pszText。通过item中的iItem,iSubItem可以知道当前显示的为那一项。下面的代码演示了这种方法:

char szOut[8][3]={"No.1","No.2","No.3"};

//添加结点

m_list.InsertItem(LPSTR_TEXTCALLBACK,...)

m_list.InsertItem(LPSTR_TEXTCALLBACK,...)

//处理消息

void CParentWnd::OnGetDispInfoList(NMHDR* pNMHDR, LRESULT* pResult)

{

LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;

pLVDI->item.pszText=szOut[pTVDI->item.iItem];

//通过iItem得到需要显示的字符在数组中的位置

*pResult = 0;

}

关于编辑某项的显示字符:(在报表风格中只对第一列有效)首先需要设置列表控件的LVS_EDITLABELS风格,在开始编辑时该控件将会发送

LVN_BEGINLABELEDIT,你可以通过在处理函数中返回TRUE来取消接下来的编辑,在编辑完成后会发送LVN_ENDLABELEDIT,在处理该消息时需要将参数

pNMHDR转换为LPNMLVDISPINFO,然后通过其中的item.pszText得到编辑后的字符,并重置显示字符。如果编辑在中途中取消该变量为NULL。下面的代码说明如何处理这些消息:

//处理消息 LVN_BEGINLABELEDIT

void CParentWnd::OnBeginEditList(NMHDR* pNMHDR, LRESULT* pResult)

{

LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;

if(pLVDI->item.iItem==0);//判断是否取消该操作

*pResult = 1;

else

*pResult = 0;

}

//处理消息 LVN_BEGINLABELEDIT

void CParentWnd::OnBeginEditList(NMHDR* pNMHDR, LRESULT* pResult)

{

LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;

if(pLVDI->item.pszText==NULL);//判断是否已经取消取消编辑

m_list.SetItemText(pLVDI->item.iItem,0,pLVDI->pszText);

//重置显示字符

*pResult = 0;

}

上面讲述的方法所进行的消息映射必须在父窗口中进行(同样WM_NOTIFY的所有消息都需要在父窗口中处理)。

如何得到当前选中项位置:在列表控件中没有一个类似于ListBox中GetCurSel()的函数,但是可以通过调用GetNextItem( -1, LVNI_ALL | LVNI_SELECTED);得到选中项位置。

list control控件中的风格选项:

m_list1.SetExtendedStyle( LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_CHECKBOXES );

LVS_EX_FULLROWSELECT表示可以点中行中的任意一个列选中这一条记录

LVS_EX_GRIDLINES表示列之间有分隔符号

LVS_EX_CHECKBOXES 表示每一行第一列是checkbox

LVCOLUMN:listviewcolumn

设置表头

lvColumn.mask = LVCF_SUBITEM|LVCF_TEXT|LVCF_WIDTH|LVCF_FMT; 设置表头风格

lvColumn.fmt = LVCFMT_CENTER; 设置表头对齐方式

lvColumn.iSubItem = i; 表头列序

lvColumn.pszText = HeaderTxt[i]; 表头名称

lvColumn.cx = 90; 表头宽度

m_list.InsertColumn(i,&lvColumn); 插入列

三、列表控制的数据结构

列表控制中包含两个非常重要的数据结构LV_ITEM和LV_COLUMN。LV_ITEM用于定义列表控制的一个表项,LV_COLUMN用于定义列表控制的一个表列,其定义格式分别为:

typedef struct _LV_ITEM {

UINT mask; //结构成员屏蔽位

int iItem; //表项索引号

int iSubItem; //子表项索引号

UINT state; //表项状态

UINT stateMask; //状态有效性屏蔽位

LPTSTR pszText; //表项名文本

int cchTextMax; //表项名最大长度

int iImage; //表项图标的索引号

LPARAM lParam; //与表项相关的32位数

}LV_ITEM;

typedef struct _LV_COLUMN {

UINT mask; //结构成员有效性屏蔽位

int fmt; //表列对齐方式

int cx; //表列的象素宽度

LPTSTR pszText; //表列的表头名

int cchTextMax; //表列名的文本长度

int iSubItem; //与表列关联的子表项索引号

}LV_COLUMN;

其中fmt可以取如下值:

LVCFMT_CENTER 表列居中对齐

LVCFMT_LEFT 表列左对齐

四、列表控制的应用示例

下面给出具体实例演示列表控制及前面的表头控制和图像列表的应用技巧。步骤如下:

1、使用VS2005新建一个工程CCLCTest,在建立过程中选择基于对话框(Dialog based)的应用;将对话框中的默认控件删除.

2、导入几个图标IDI_ICON1-IDI_ICON8,用来装载到LVS_ICON ,LVS_SMALLICON风格的CListCtrl中.

3、在对话框的最右边加入一个CListCtrl,代码中会实现该控件的风格切换.

4、在对话框窗口中设计组合框(Group Box),组合框中设置四个无线按钮(Radio),分别用来切换"大图标、小图标、列表、报表"风格,在设置无线按钮时,需要注意的是只有大图标的Group属性为选中状态,而其它无线按钮的状态均为默认值.

5、在Resource.h中添加资源ID

#define IDC_LIST2 103

#define IDC_LIST3 104

#define IDC_LIST4 105

#define IDC_LIST5 106

6、在程序增加下列代码:

void CCLCTestDlg::DoDataExchange(CDataExchange* pDX)

{

// 其他代码...

// 将手动添加控件与变量m_lstCtrlOne关联

DDX_Control(pDX, IDC_LIST1, m_lstCtrlOne);

}

BOOL CCLCTestDlg::OnInitDialog()

{

/* 其他代码 */

// 设置大图标的Radio按钮为选中状态

((CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(BST_CHECKED);

// 自定义函数. 创建 "大图标、小图标、列表、报表" 四种风格的CListCtrl

CreateListCtrl();

// 自定义函数. 为大图标和小图标风格的CListCtrl创建和加载图标链表

CreateImageList();

// 自定义函数. 插入Column的两种方法(只对Report风格的报表有效)

InsertColumn();

// 自定义函数. 插入行的两种方法

InsertItem();

// 自定义函数. 更改行的两种方法

SetItemInfo();

return TRUE; // return TRUE unless you set the focus to a control

}

// 创建报表、图标、小图标和列表四种ListCtrl控件

void CCLCTestDlg::CreateListCtrl(void)

{

CRect rect;

CRect rectTmp;

GetClientRect(&rect);
rectTmp.left = rect.left + 10;

rectTmp.top = rect.top + 10;

rectTmp.right = rectTmp.left + rect.Width() / 3 - 10;

rectTmp.bottom = rectTmp.top + rect.Height() / 2 - 50;

// 创建CListCtrl控件, 报表风格(m_lstCtrlRpt)

m_lstCtrlRpt.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT, rectTmp, this, IDC_LIST2);
rectTmp.left = rectTmp.right + 20;

rectTmp.right = rectTmp.left + rect.Width() / 3 - 10;

// 创建CListCtrl控件, 大图标风格(m_lstCtrlIcon)

m_lstCtrlIcon.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_ICON, rectTmp, this, IDC_LIST3);
rectTmp.top = rectTmp.bottom + 10;

rectTmp.bottom = rectTmp.top + rect.Height() / 2 - 30;

// 创建CListCtrl控件, 小图标风格(m_lstCtrlSIcon)

m_lstCtrlSIcon.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_SMALLICON, rectTmp, this, IDC_LIST4);
rectTmp.right = rectTmp.left - 20;

rectTmp.left = rectTmp.right - rect.Width() / 3 + 10;

// 创建CListCtrl控件, 列表风格(m_lstCtrlList)

m_lstCtrlList.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_LIST, rectTmp, this, IDC_LIST5);

}

// 创建图表链表

void CCLCTestDlg::CreateImageList(void)

{

// 创建图标链表

m_ImageListBig.Create(IDB_BITMAP1, 64, 0, RGB(0,0,0));

CCLCTestApp* pApp = (CCLCTestApp*)AfxGetApp();

m_ImageListSmall.Create(32, 32, TRUE, 0, 8);

m_ImageListSmall.Add(pApp->LoadIcon(IDI_ICON1));

m_ImageListSmall.Add(pApp->LoadIcon(IDI_ICON2));

m_ImageListSmall.Add(pApp->LoadIcon(IDI_ICON3));

m_ImageListSmall.Add(pApp->LoadIcon(IDI_ICON4));

m_ImageListSmall.Add(pApp->LoadIcon(IDI_ICON5));

m_ImageListSmall.Add(pApp->LoadIcon(IDI_ICON6));

m_ImageListSmall.Add(pApp->LoadIcon(IDI_ICON7));

m_ImageListSmall.Add(pApp->LoadIcon(IDI_ICON8));

// 设置图标链表

m_lstCtrlList.SetImageList(&m_ImageListBig, LVSIL_NORMAL);

m_lstCtrlIcon.SetImageList(&m_ImageListBig, LVSIL_NORMAL);

m_lstCtrlSIcon.SetImageList(&m_ImageListSmall, LVSIL_SMALL);

}

// 插入列头

void CCLCTestDlg::InsertColumn(void)

{

CRect rectTmp;

m_lstCtrlRpt.GetClientRect(&rectTmp);

// 插入列, 只有Report才用此函数

// 第一种:使用LV_COLUMN插入

LV_COLUMN lvcol;

lvcol.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
lvcol.fmt = LVCFMT_CENTER;

int i = 0;

lvcol.pszText = _T("第一列");

lvcol.iSubItem = i;

lvcol.cx = rectTmp.Width() / 4;

m_lstCtrlRpt.InsertColumn(i++, &lvcol);
lvcol.pszText = _T("第二列");

lvcol.iSubItem = i;

m_lstCtrlRpt.InsertColumn(i++, &lvcol);

// 第二种:直接插入

m_lstCtrlRpt.InsertColumn(i++, _T("第三列"), LVCFMT_LEFT, rectTmp.Width() / 4);

m_lstCtrlRpt.InsertColumn(i++, _T("第四列"), LVCFMT_LEFT, rectTmp.Width() / 4);

}

// 插入行

void CCLCTestDlg::InsertItem(void)

{

// 插入行

// 第一种:使用LV_ITEM插入

LV_ITEM lvitem;

int iIndex;
lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;

lvitem.iItem = 0;

lvitem.iSubItem = 0;

lvitem.pszText = _T("第一个");

lvitem.iImage = 0;

lvitem.lParam = 0;

iIndex = m_lstCtrlRpt.InsertItem(&lvitem);
lvitem.mask = LVIF_TEXT;

lvitem.iItem = iIndex;

lvitem.iSubItem = 1;

lvitem.pszText = _T("第二个");

m_lstCtrlRpt.SetItem(&lvitem);
lvitem.iSubItem = 2;

lvitem.pszText = _T("第三个");

m_lstCtrlRpt.SetItem(&lvitem);
m_lstCtrlRpt.SetItemText(0, 3, _T("第四个"));

// 第二种:直接插入

m_lstCtrlIcon.InsertItem(0, _T("一"), 0);

m_lstCtrlIcon.InsertItem(1, _T("二"), 1);

m_lstCtrlIcon.InsertItem(2, _T("三"), 2);

m_lstCtrlIcon.InsertItem(3, _T("四"), 3);

m_lstCtrlIcon.InsertItem(4, _T("五"), 4);

m_lstCtrlIcon.InsertItem(5, _T("六"), 5);
m_lstCtrlSIcon.InsertItem(0, _T("一"), 0);

m_lstCtrlSIcon.InsertItem(1, _T("二"), 1);

m_lstCtrlSIcon.InsertItem(2, _T("三"), 2);

m_lstCtrlSIcon.InsertItem(3, _T("四"), 3);

m_lstCtrlSIcon.InsertItem(4, _T("五"), 4);

m_lstCtrlSIcon.InsertItem(5, _T("六"), 5);
m_lstCtrlList.InsertItem(0, _T("一"), 0);

m_lstCtrlList.InsertItem(1, _T("二"), 1);

m_lstCtrlList.InsertItem(2, _T("三"), 2);

m_lstCtrlList.InsertItem(3, _T("四"), 3);

m_lstCtrlList.InsertItem(4, _T("五"), 4);

m_lstCtrlList.InsertItem(5, _T("六"), 5);

}

// 更改行数据

void CCLCTestDlg::SetItemInfo(void)

{

// 第一种方法

m_lstCtrlRpt.SetItemText(1, 0, _T("第一种更改方法"));

m_lstCtrlIcon.SetItemText(1, 0, _T("第一种更改方法"));

m_lstCtrlSIcon.SetItemText(1, 0, _T("第一种更改方法"));

m_lstCtrlList.SetItemText(1, 0, _T("第一种更改方法"));

//第二种方法

LV_ITEM lvitem;
lvitem.mask = LVIF_TEXT | LVIF_IMAGE;

lvitem.iItem = 0;

lvitem.iSubItem = 0;

lvitem.pszText = _T("第二种更改方法");

lvitem.iImage = 2;
m_lstCtrlRpt.SetItem(&lvitem);

m_lstCtrlIcon.SetItem(&lvitem);

m_lstCtrlSIcon.SetItem(&lvitem);

m_lstCtrlList.SetItem(&lvitem);

}

// 设置CListCtrl控件m_lstCtrlOne为大图标风格

void CCLCTestDlg::OnBnRadioBig()

{

LONG lStyle;

lStyle = GetWindowLong(m_lstCtrlOne.m_hWnd, GWL_STYLE); //获取当前窗口类型

lStyle &= ~LVS_TYPEMASK; //清除显示方式位

lStyle |= LVS_ICON; //设置显示方式
SetWindowLong(m_lstCtrlOne.m_hWnd, GWL_STYLE, lStyle); //设置窗口类型

}

// 设置CListCtrl控件m_lstCtrlOne为小图标风格

void CCLCTestDlg::OnBnRadioSmall()

{

LONG lStyle;

lStyle = GetWindowLong(m_lstCtrlOne.m_hWnd, GWL_STYLE); //获取当前窗口类型

lStyle &= ~LVS_TYPEMASK; //清除显示方式位

lStyle |= LVS_SMALLICON; //设置显示方式
SetWindowLong(m_lstCtrlOne.m_hWnd, GWL_STYLE, lStyle);
//设置窗口类型

}

// 设置CListCtrl控件m_lstCtrlOne为报表风格

void CCLCTestDlg::OnBnRadioReport()

{

LONG lStyle;

lStyle = GetWindowLong(m_lstCtrlOne.m_hWnd,GWL_STYLE);
//获取当前窗口类型

lStyle &= ~LVS_TYPEMASK; //清除显示方式位

lStyle |= LVS_REPORT; //设置显示方式
SetWindowLong(m_lstCtrlOne.m_hWnd, GWL_STYLE, lStyle); //设置窗口类型

}

// 设置CListCtrl控件m_lstCtrlOne为列表风格

void CCLCTestDlg::OnBnRadioList()

{

LONG lStyle;

lStyle = GetWindowLong(m_lstCtrlOne.m_hWnd,GWL_STYLE); //获取当前窗口类型

lStyle &= ~LVS_TYPEMASK; //清除显示方式位

lStyle |= LVS_LIST; //设置显示方式
SetWindowLong(m_lstCtrlOne.m_hWnd, GWL_STYLE, lStyle);
//设置窗口类型

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: