VC通用控件编程之CList控件

翻译|其它|编辑:郝浩|2007-09-21 09:16:39.000|阅读 1185 次

概述:

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

(一)列表控制的主要功能

列表控制和视(List Control&View)主要用来以各种方式显示一组数据记录供用户进行各种操作,Windows98/95中资源管理器中的查看标签下的大图标|小图标|列表|详细资源就是一个非常好的典型应用。列表中的记录可以包括多个数据项,也可以包括表示数据内容的大小图标,用来表示数据记录的各种属性。

列表控制提供了对  Windows  列表功能操作的基本方法,而使用列表视的视函数可以对列表视进行各种操作,通过调用视成员  GetListCtrl  获取嵌在列表视内列表控制的引用(GetListCtrl& ctrlList = GetListCtrl()),就可以和列表控制一样进行各种操作。操作一个列表控制和视的基本方法为:创建列表控制;创建列表控制所需要的图像列表;向列表控制添加表列和表项;对列表进行各种控制,主要包括查找、排序、删除、显示方式、排列方式以及各种消息处理功能等;最后撤消列表控制。

对于一个列表控制,其最典型最常用的显示控制方式为:大图标方式(LVS_ICON)、小图标方式(LVS_SMALLICON)、列表显示方式(LVS_LIST)和详细资料(即报告LVS_REPORT)显示方式。这可以通过设置其显示方式属性来实现。要控制列表所在窗口的风格,可通过功能函数  GetWindowLong    SetWindowLong  来实现,要控制列表图标的对齐方式,可通过设置列表窗口的风格  LVS_ALIGNTOP    LVS_ALIGNLEFT  来实现,

(二)列表控制的对象结构

1、列表控制的建立方法

CListCtrllistCtrl  定义列表对象的结构

Create  建立列表控制并绑定对象

列表控制  CListCtrl::Create  的调用格式如下:

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

其中参数  dwStyle  用来确定列表控制的风格;rect  用来确定列表控制的大小和位置;pParentWnd  用来确定列表控制的父窗口,通常是一个对话框;nID  用来确定列表控制的标识。其中列表控制的风格可以是下列值的组合:

LVS_ALIGNLEFT  用来确定表项的大小图标以左对齐方式显示;

LVS_ALIGNTOP  用来确定表项的大小图标以顶对齐方式显示;

LVS_AUTOARRANGE  用来确定表项的大小图标以自动排列方式显示;

LVS_EDITLABELS  设置表项文本可以编辑,父窗口必须设有  LVN_ENDLABELEDIT  风格;

LVS_ICON  用来确定大图标的显示方式;

LVS_LIST  用来确定列表方式显示;

LVS_NOCOLUMNHEADER  用来确定在详细资料方式时不显示列表头;

LVS_NOLABELWRAP  用来确定以单行方式显示图标的文本项;

LVS_NOSCROLL  用来屏蔽滚动条;

LVS_NOSORTHEADER  用来确定列表头不能用作按钮功能;

LVS_OWNERDRAWFIXED  在详细列表方式时允许自绘窗口;

LVS_REPORT  用来确定以详细资料即报告方式显示;

LVS_SHAREIMAGELISTS  用来确定共享图像列表方式;

LVS_SHOWSELALWAYS  用来确定一直显示被选中表项方式;

LVS_SINGLESEL 用来确定在某一时刻只能有一项被选中;

LVS_SMALLICON  用来确定小图标显示方式;

LVS_SORTASCENDING  用来确定表项排序时是基于表项文本的升序方式;

LVS_SORTDESCENDING  用来确定表项排序时是基于表项文本的降序方式;

2、列表控制的属性类

列表控制的属性类包括取得列表控制的背景色  GetBkColor、设置列表控制的背景色  SetBkColor、取得列表控制的图像列表  GetImageList、设置列表控制的图像列表  SetImageList、取得列表项数目  GetItemCount、取得列表控制的属性  GetItem、取得与表项相关的数据  GetItemData、设置表项的属性  SetItem、设置与表项相关的数值  SetItemData、取得相关联的下一个表项  GetNextItem、设置列表控制的文本颜色  SetTextColor、取得列表控制的文本背景颜色  GetTextBkColor、设置表项的最大数目  SetItemCount和取得被选中表项的数目  GetSelectedCount  等。

3、列表控制的操作方法

列表控制的操作方法包括插入一个新的表项  InsertItem、删除一个表项  DeleteItem、排序表项SortItems、测试列表的位置  HitTest、重绘表项  RedrawItems、插入一个表列  InsertColumn、删除一个表列  DeleteColumn、编辑一个表项文本  EditLabel  和重绘一个表项  DrawItem  等。

(三)列表控制的数据结构

列表控制中包含两个非常重要的数据结构  LV_ITEM    LV_COLUMNLV_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、通过“FILE->NEW->PROJECTS->MFC AppWizard(EXE)”建立名为  VCLIST  的工程,在建立过程中选择基于对话框(Dialog based)的应用;将对话框中的默认控件删除,并将所有对话框属性中的  Language  域设置为  Chinese(P.R.C.),以使应用程序支持中文;

2、建立两个图标  IDI_GJ    IDI_XS,用来表示图标的选中和非选中状态,对于每个图标都应建立32X3216X16两种大小,以保证程序的需要;

3、在对话框窗口中设计组合框(Group Box,组合框中设置四个无线按钮(Radio大图标|小图标|列表|资料,同时设置排序、删除和关闭三个控制按钮(Button),并在对话框中设置大小合适的列表控制(List Ctrl),其对应标识分别如下:

--------------------------------------------------------------------------------

控制名称 标题名称 标识符号


--------------------------------------------------------------------------------

列表控制  IDC_LISTCTRL

组合框 方式  IDC_STATIC

无线按钮大图标  IDC_STDICON

小图标  IDC_SMLICON

 IDC_LIST

 IDC_REPORT

按钮排序  IDC_SORT

 IDC_DEL

 IDOK


--------------------------------------------------------------------------------

4、在设置无线按钮时,需要注意的是只有大图标的  Group  属性为选中状态,而其它无线按钮的状态均为默认值。

5、选中列表控制控件,选择“VIEW->ClassWizard->Memory Variables”,并利用  IDC_ LISTCTRL  引入成员变量,其变量类型为:

变量名 种类 变量类型

m_ListCtrl Control ClistCtrl

同时利用“MESSAGES MAP”为各无线按钮和命令按钮增加控制功能。

6、然后在包含文件和代码文件中分别加入如下代码:

a)在  VCLISTDlg.h  中增加数据结构和定义

typedef struct tagSPS { //定义结构

char szPm[10]; //品名

int Lx; //0-GJ 1-XS

char szSl[10]; //数量

char szDj[10]; //单价

char szJe[10]; //金额

} SPS;

int CALLBACK CompareFunc(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort);

b)在  VCLISTDlg.CPP  中的起始处增加初始化数据和程序定义

//在文件开始处增加数据结构初始化

SPS Sps[]={//信息

{"红梅",0,"1000","30","30000"},

{"黄梅",0,"1000","29","29000"},

{"绿梅",0,"1000","28","28000"},

{"青梅",0,"1000","27","27000"},

{"白梅",0,"1000","31","31000"},

{"红梅",1,"1000","30","30000"},

{"黄梅",1,"1000","29","29000"},

{"绿梅",1,"1000","28","28000"},

{"青梅",1,"1000","27","27000"},

{"白梅",1,"1000","31","31000"}};

CImageList Cil1,Cil2;//大小图像列表

c)在程序初始化处增加表头、图像和列表控制建立代码

BOOL CVCLISTDlg::OnInitDialog()

{CDialog::OnInitDialog();

//......//其它代码

// TODO: Add extra initialization here  此处增加代码

LV_ITEM lvitem;

LV_COLUMN lvcol;

int i,iPos,iItemNum;

CVCLISTApp *pApp=(CVCLISTApp *)AfxGetApp();//创建图象列表

Cil1.Create(32,32,TRUE,2,2);

Cil1.Add(pApp->LoadIcon(IDI_GJ));

Cil1.Add(pApp->LoadIcon(IDI_XS));

Cil2.Create(16,16,TRUE,2,2);

Cil2.Add(pApp->LoadIcon(IDI_GJ));

Cil2.Add(pApp->LoadIcon(IDI_XS));//设置图象列表

m_ListCtrl.SetImageList(&Cil1,LVSIL_NORMAL);

m_ListCtrl.SetImageList(&Cil2,LVSIL_SMALL);//向列表控制中添加表列

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

lvcol.fmt=LVCFMT_CENTER;//居中

i=0;

lvcol.pszText=" ";

lvcol.iSubItem=i;

lvcol.cx=70;

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

lvcol.pszText=" ";

lvcol.iSubItem=i;

lvcol.cx=70;

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

lvcol.pszText=" ";

lvcol.iSubItem=i;

lvcol.cx=70;

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

lvcol.pszText=" ";

lvcol.iSubItem=i;

lvcol.cx=70;

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

//向列表控制中添加表项

iItemNum=sizeof(Sps)/sizeof(SPS);

for(i=0;i<iItemNum;i++){

lvitem.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;

lvitem.iItem=i;

lvitem.iSubItem=0;

lvitem.pszText=Sps[i].szPm;

lvitem.iImage=Sps[i].Lx;

lvitem.lParam=i;

iPos=m_ListCtrl.InsertItem(&lvitem);//返回表项插入后的索引号

lvitem.mask=LVIF_TEXT;

lvitem.iItem=iPos;

lvitem.iSubItem=1;

lvitem.pszText=Sps[i].szSl;

m_ListCtrl.SetItem(&lvitem);

lvitem.iSubItem=2;

lvitem.pszText=Sps[i].szDj;

m_ListCtrl.SetItem(&lvitem);

lvitem.iSubItem=3;

lvitem.pszText=Sps[i].szJe;

m_ListCtrl.SetItem(&lvitem);

}

CheckRadioButton(IDC_STDICON,IDC_REPORT,IDC_STDICON);

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

}

d)完善列表显示方式代码

在利用  Classwizard  类向导创建各功能按钮显示功能函数之后,必须依次完善这些功能函数的代码,这些功能函数如下:

void CVCLISTDlg::OnStdicon()//设置大图标显示方式

{ // TODO: Add your control notification handler code here

LONG lStyle;

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

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

lStyle|=LVS_ICON; //设置显示方式

SetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE,lStyle);//设置窗口类型

}

void CVCLISTDlg::OnSmlicon() //设置小图标显示方式

{ // TODO: Add your control notification handler code here

LONG lStyle;

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

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

lStyle|=LVS_SMALLICON; //设置显示方式

SetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE,lStyle);//设置窗口类型

}

void CVCLISTDlg::OnList() //设置列表显示方式

{ // TODO: Add your control notification handler code here

LONG lStyle;

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

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

lStyle|=LVS_LIST; //设置显示方式

SetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE,lStyle);//设置窗口类型

}

void CVCLISTDlg::OnReport() //详细资料显示方式

{ // TODO: Add your control notification handler code here

LONG lStyle;

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

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

lStyle|=LVS_REPORT; //设置显示方式

SetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE,lStyle);//设置窗口类型

}

e)删除功能的实现

要实现删除功能,必须取得选中表项的数和表项总数,并且需要从后向前进行依次删除,其原因是每个表项被删除后,其后各表项的索引号均会发生递减变化,如果采取从前向后删除的方法,就会造成无法正常删除选中的表项,其功能代码如下:

void CVCLISTDlg::OnDel() //删除按钮功能

{ // TODO: Add your control notification handler code here

int i,iState;

int nItemSelected=m_ListCtrl.GetSelectedCount();//所选表项数

int nItemCount=m_ListCtrl.GetItemCount();//表项总数

if(nItemSelected<1) return;

for(i=nItemCount-1;i>=0;i--){

iState=m_ListCtrl.GetItemState(i,LVIS_SELECTED);

if(iState!=0) m_ListCtrl.DeleteItem(i);

}

}

f)排序功能的实现

列表控制有一个特殊的功能,当以详细资料方式显示时,列表顶部的表头可以当作按钮来使用,这可以通过列表控制创建时的风格来控制。当鼠标点击列表头名称时,列表控制就会向其父窗口发送一个  LNV_COLUMNCLICK  消息,利用类导向中列表控制  IDC_LISTCTRL  对应的  LNV_COLUMNCLICK  消息加入相应处理函数,就可将表列按照特定顺序进行排列。其函数使用方法见程序,其中  iSort  为排序的表列索引号,(PFNLVCOMPARE)CompareFunc  为进行具体排序的回调函数,也就是说,通过鼠标点击表头实现的排序过程是由第三方开发的专用排序函数来实现的,排序函数只是实现表项的具体比较操作,而整个排序过程是由  SortItemS  属性通过不断调用这个函数来实现的。正常的排序过程是升序方式,通过调换排序函数中的参数值,就可实现降序排列,即将  PARAM1    PARAM2  调换位置。这个回调函数的前两个参数为表列中表项的索引号,第三个参数为排序的表列索引号。

void CVCLISTDlg::OnColumnclickListctrl(NMHDR* pNMHDR, LRESULT* pResult)

{ //鼠标左键单击表头处理函数

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

// TODO: Add your control notification handler code here

static int iSorted=-1;//排列序号

if (pNMListView->iSubItem==iSorted) return;

iSorted=pNMListView->iSubItem;

m_ListCtrl.SortItems((PFNLVCOMPARE)CompareFunc,iSorted);

*pResult = 0;

}

//排序时比较表项的回调函数

int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2,LPARAM lParamSort)

{ char *text1,*text2;

switch (lParamSort){

case 0L:text1=Sps[lParam1].szPm;

text2=Sps[lParam2].szPm;break;

case 1L:text1=Sps[lParam1].szSl;

text2=Sps[lParam2].szSl;break;

case 2L:text1=Sps[lParam1].szDj;

text2=Sps[lParam2].szDj;break;

case 3L:text1=Sps[lParam1].szJe;

text2=Sps[lParam2].szJe;break;

}

return (strcmp(text1,text2));//结果为>0 =0 <0

}

同样,也可以通过专用按钮来实现排序功能,如本文的排序按钮对应的功能代码如下:

void CVCLISTDlg::OnSort()

{ // TODO: Add your control notification handler code here

m_ListCtrl.SortItems((PFNLVCOMPARE)CompareFunc,0);}

(g)、列表视的演练技巧

在使用列表视时,其方法与列表控制基本相同,只不过列表视是在窗口中来实现的而列表控制是在对话框中实现,列表视的各种功能是通过菜单来实现的而列表控制是通过按钮等方式来实现的,列表控制需要在对话框中创建列表控制控件而列表视直接占据整个窗口,在设计过程中只要将按钮和列表控制设计过程变为菜单设计,并注意在功能增加是在类向导中是通过菜单命令来操作,同时在每个功能函数前面增加取得列表视引用的命令(CListCtrl& ListCtrl = GetListCtrl()),而其余数据结构和代码均不需要修改,实现起来比较容易。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:csdn

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP