MFC CListCtrl的使用说明

  CListCtrl的使用说明: 
       
  (一)列表控制的主要功能  
   
  列表控制和视(List   Control&View)主要用来以各种方式显示一组数据记录供用户进行各种操作,Windows9X中资源管理器中的“查看”标签下的“大图标|小图标|列表|详细资源”就是一个非常好的典型应用。列表中的记录可以包括多个数据项,也可以包括表示数据内容的大小图标,用来表示数据记录的各种属性。  
   
  列表控制提供了对Windows列表功能操作的基本方法,而使用列表视的视函数可以对列表视进行各种操作,通过调用视成员GetListCtrl获取嵌在列表视内列表控制的引用(GetListCtrl&   ctrlList   =   GetListCtrl()),就可以和列表控制一样进行各种操作。操作一个列表控制和视的基本方法为:创建列表控制;创建列表控制所需要的图像列表;向列表控制添加表列和表项;对列表进行各种控制,主要包括查找、排序、删除、显示方式、排列方式以及各种消息处理功能等;最后撤消列表控制。  
   
  对于一个列表控制,其最典型最常用的显示控制方式为:大图标方式(LVS_ICON)、小图标方式(LVS_SMALLICON)、列表显示方式(LVS_LIST)和详细资料(即报告LVS_REPORT)显示方式。这可以通过设置其显示方式属性来实现。要控制列表所在窗口的风格,可通过功能函数GetWindowLong和SetWindowLong来实现,要控制列表图标的对齐方式,可通过设置列表窗口的风格LVS_ALIGNTOP或LVS_ALIGNLEFT来实现,  
   
  (二)列表控制的对象结构  
   
  1、列表控制的建立方法  
   
  CListCtrl&listCtrl   定义列表对象的结构  
   
  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   用来确定表项排序时是基于表项文本的降序方式;   
 
 
 
dwNewStyle指定的扩展样式

  LVS_EX_GRIDLINES //绘制表格,网格线。

  LVS_EX_SUBITEMIMAGES//子项目图标列表

  LVS_EX_CHECKBOXES //带复选框

  LVS_EX_TRACKSELECT //自动换行

  LVS_EX_HEADERDRAGDROP//报表头可以拖拽

  LVS_EX_FULLROWSELECT //选择整行,允许选择整行。

  LVS_EX_ONECLICKACTIVATE//单击激活单击选中项目。

  LVS_EX_TWOCLICKACTIVATE//双击激活

  LVS_EX_FLATSB//扁平滚动条

  LVS_EX_REGIONAL

  LVS_EX_INFOTIP

  LVS_EX_UNDERLINEHOT

  LVS_EX_UNDERLINECOLD

  LVS_EX_MULTIWORKAREAS//多工作区

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
设置listctrl 风格及扩展风格
LONG lStyle;
      lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口style
      lStyle &= ~LVS_TYPEMASK; //清除显示方式位
      lStyle |= LVS_REPORT; //设置style
      SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置style

      DWORD dwStyle = m_list.GetExtendedStyle();
      dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl)
      dwStyle |= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl)
      dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件
      m_list.SetExtendedStyle(dwStyle); //设置扩展风格 
  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_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、通过“FILE->NEW->PROJECTS->MFC   AppWizard(EXE)”建立名为VCLIST的工程,在建立过程中选择基于对话框(Dialog   based)的应用;将对话框中的默认控件删除,并将所有对话框属性中的Language域设置为Chinese(P.R.C.),以使应用程序支持中文;       
  建立两个图标IDI_GJ和IDI_XS,用来表示图标的选中和非选中状态,对于每个图标都应建立32X32和16X16两种大小,以保证程序的需要;    
  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、然后在包含文件和代码文件中分别加入如下代码:  
   
  (1)在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);  
   
  (2)在VCLISTDlg.CPP中的起始处增加初始化数据和程序定义  
   
  //在文件开始处增加数据结构初始化  
   
  SPS   Sps[]={//信息  
   
  {"红梅",0,"1000","30","30000"},           
       
  CImageList   Cil1,Cil2;//大小图像列表  
   
  (3)在程序初始化处增加表头、图像和列表控制建立代码  
   
  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  
   
  }  
   
  (4)完善列表显示方式代码  
   
  在利用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);//设置窗口类型  
   
  }  
   
  (5)删除功能的实现  
   
  要实现删除功能,必须取得选中表项的数和表项总数,并且需要从后向前进行依次删除,其原因是每个表项被删除后,其后各表项的索引号均会发生递减变化,如果采取从前向后删除的方法,就会造成无法正常删除选中的表项,其功能代码如下:  
   
  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);     
     
  }  
   
  (6)排序功能的实现  
   
  列表控制有一个特殊的功能,当以详细资料方式显示时,列表顶部的表头可以当作按钮来使用,这可以通过列表控制创建时的风格来控制。当鼠标点击列表头名称时,列表控制就会向其父窗口发送一个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);}  
   
  7、列表视的演练技巧  
   
  在使用列表视时,其方法与列表控制基本相同,只不过列表视是在窗口中来实现的而列表控制是在对话框中实现,列表视的各种功能是通过菜单来实现的而列表控制是通过按钮等方式来实现的,列表控制需要在对话框中创建列表控制控件而列表视直接占据整个窗口,在设计过程中只要将按钮和列表控制设计过程变为菜单设计,并注意在功能增加是在类向导中是通过菜单命令来操作,同时在每个功能函数前面增加取得列表视引用的命令(   CListCtrl&   ListCtrl   =   GetListCtrl()),而其余数据结构和代码均不需要修改,实现起来比较容易。 
 
 
 
 
//--------------------------------------------------------------------------------------------

    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 用来确定表项排序时是基于表项文本的降序方式;


 

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 表列左对齐



CListCtrl  使用完全指南

构造函数

  ClistCtrl构造一个CListCtrl对象。

  Create创建列表控件并将其附加给CListCtrl对象。

属性

  GetBkColor获取列表视图控件的背景色。

  SetBkColor设置列表视图控件的背景色。

  GetImageList获取用于绘制列表视图项的图象列表的句柄。

  SetImageList指定一个图象列表到列表视图控件。

  GetItemCount获取列表视图控件中的项的数量。

  GetItem获取列表视图项的属性。

  GetCallbackMask获取列表视图控件的回调掩码。

  SetCallbackMask设置列表视图控件的回调掩码。

  GetNextItem查找指定特性和指定指定项关系的列表视图项。

  GetFirstSeletedItemPosition在列表视图控件中获取第一个选择的列表视图项的位置。

  GetNextSeletedItem为重复而获取下一个选择的列表视图。

  GetItemRect获取项的有界矩形。

  SetItemPosition在列表视图控件中移动一项到指定位置。

  GetItemPosition获取列表视图项的位置。

  GetStringWidth指定需要显示所有指定字符串的最小列宽。

  GetEditControl获取用于编辑一个项文本的编辑控件的句柄。

  GetColumn获取控件的列的属性。

  SetColumn设置列表视图列的属性。

  GetColumnWidth获取报表视图或列表视图中的列的宽度。

  SetColumnWidth改变报表视图或列表视图中的列的宽度。

  GetCheck获取与某项相关的状态图象的当前显示状态。

  SetCheck设置与某项相关的状态图象的当前显示状态。

  GetViewRect获取列表视图控件中所有项的有界矩形。

  GetTextColor获取列表视图控件的文本颜色。

  SetTextColor设置列表视图控件的文本颜色。

  GetTextBkColor获取列表视图控件的文本背景色。

  SetTextBkColor设置列表视图控件的文本背景色。

  GetTopIndex获取最高级项的索引。

  GetCountPerPage计算可正好垂直放入列表视图控件中的项的数目。

  GetOrigin获取列表视图控件的最初的当前视图。

  SetItemState改变列表视图控件的项的状态。

  GetItemState获取列表视图控件的项的状态。

  GetItemText获取列表视图项或子项的文本。

  SetItemText设置列表视图项或子项的文本。

  SetItemCount准备一个列表视图控件以添加大量的项。

  GetItemData获取与某项相关的应用所指定的值。

  SetItemData设置项的应用指定的值。

  GetSelectedCount获取列表视图控件中选择项的数量。

  SetColumnOrderArray设置列表视图控件的列序(左或右)。

  GetColumnOrderArray获取列表视图控件的列序(左或右)。

  SetIconSpacing设置列表视图控件中的图标的距离。

  GetHeaderCtrl获取列表视图控件的标题控件。

  GetHotCursor获取在热调试对列表视图控件有效时使用的游标。

  SetHotCursor设置在热调试对列表视图控件有效时使用的游标。

  GetSubItemRect获取列表视图控件中某项的有界矩形。

  GetHotItem获取当前在游标下的列表视图项。

  SetHotItem设置列表视图控件的当前热项。

  GetSelectionMark获取列表视图控件的选择屏蔽。

  SetSelectionMark设置列表视图控件的选择屏蔽。

  GetExtendedStyle获取列表视图控件的当前扩展风格。

  SetExtendedStyle设置列表视图控件的当前扩展风格。

  SubItemHitTest指定哪个列表视图项在指定位置。

  GetWorkAreas获取列表视图控件的当前工作区。

  GetNumberOfWorkAreas获取列表视图控件的当前工作区数量。

  SetItemCountEx设置虚列表视图控件的项的数量。

  SetWorkAreas设置列表视图控件中图标可以显示的区域。

  ApproximateViewRect指定显示列表视图控件项所需的宽度和高度。

  GetBkImage获取列表视图控件的当前背景图象。

  SetBkImage设置列表视图控件的当前背景图象。

  GetHoverTime获取列表视图控件的当前逗留时间。

  SetHoverTime设置列表视图控件的当前逗留时间。

操作

  InsertItem在列表视图控件中插入一个新项。

  DeleteItem从控件中删除一项。

  DeleteAllItems从控件中删除所有项。

  FindItem查找具有指定的字符的列表视图项。

  SortItems使用应用定义的比较函数排序列表视图项。

  HitTest指定哪个列表视图在指定的位置上。

  EnsureVisible保证项是可见的。

  Scroll滚动列表视图控件的内容。

  ReDrawItems强迫列表视图控件刷新一些项。

  Update强迫控件刷新一个指定的项。

  Arrange调整一栏里的项。

  EditLabel开始项文本该处编辑。

  InsertColumn插入列表视图控件中的新列。

  DeleteColumn从列表视图控件中删除一列。

  CreateDragImage为指定的项构造一个拖动图象列表。

可覆盖的函数

  DrawItem当自绘制控件的可视部分改变时被调用。

 

创建图形列表并和CListCtrl关联:
 m_image_list.Create(IDB_CALLER2, 16, 10, RGB(192,192, 192));
 m_image_list.SetBkColor( GetSysColor( COLOR_WINDOW ) );
 m_caller_list.SetImageList( &m_image_list, LVSIL_SMALL);
为报表添加4列:
  char *szColumn[]={"昵称","IP地址","登陆时间","状态"};
  int widths[]={100,98,70,55};
  LV_COLUMN lvc;
  lvc.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
  lvc.fmt=LVCFMT_LEFT;
  for(int i=0;i<4;i++) {//插入各列
   lvc.pszText=szColumn[i];
   lvc.cx=widths[i];
   lvc.iSubItem=i;
   m_caller_list.InsertColumn(i,&lvc);
  }
为报表添加两项,以附加方式添加:
 char* data[4];
 data[0]="所有人";
 data[1]="0.0.0.0";
 data[3]="在线";
 data[2]=new char;
 CTime now=CTime::GetCurrentTime();
       CString temp =now.Format("%H:%M:%S");
 data[2]=temp.GetBuffer(1);
 LV_ITEM lvi;
 lvi.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
 lvi.iSubItem=0;
 lvi.pszText=(char *)data[0];
 lvi.iImage = 0;
 lvi.iItem=0;
 m_caller_list.InsertItem(&lvi);
 for (int j=0;j<4;j++) m_caller_list.SetItemText(count,j,data[j]);
 count++;
 lvi.iImage = 1;
 lvi.iItem=count;
 m_caller_list.InsertItem(&lvi);
 data[0]="cherami";
 data[1]="127.0.0.1"; 
 for (int n=0;n<4;n++) m_caller_list.SetItemText(count,n,data[n]);
 count++;

设置报表的样式
选中一整行:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_FULLROWSELECT);  
绘制表格:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_GRIDLINES); 
带复选框:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_CHECKBOXES); 
自动切换:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_TRACKSELECT);

选定一行:
设置CListCtrl的Show selectionalways选项
SetItemState (iIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED) 
 
选中一个或多个项目时,会发送LVN_ITEMCHANGED消息,可以使用
GetSelectedCount()方法得到被选定的项的数目。

点击列头的消息响应:
ON_NOTIFY(HDN_ITEMCLICKW, 0, ResponseFunc)
消息,需要自己添加 
或者:
ON_NOTIFY(LVN_COLUMNCLICK, ID_yourCtrl,  ResponseFunc)//向导添加
前者后响应,后者先响应

响应函数:
ResponseFunc(NMHDR *pNMHDR, LRESULT *pResult)

双击CListCtrl中的ITEM的消息是及消息函数:
ON_NOTIFY(NM_DBLCLK, ID_yourCtrl, ResponseFunc)

单击ITEM的消息响应:
ON_NOTIFY(NM_CLICK, ID_yourCtrl, ResponseFunc)
ResponseFunc(NMHDR *pNMHDR, LRESULT *pResult)


HDN_ITEMCLICK    就是Header controlNotify message for mouse left click on the Header control!
而HDN_ITEMCLICK是当List View中存在一个Header Contrl时,Header Ctrl通知父窗口List View的!

CListCtrl中的Item被选中触发LBN_SELCHANGE(通过WM_COMMAND)消息!

删除CListCtrl中选定的项:
POSITION pos;
int nIndex;

for(; pos= GetFirstSelectedItemPosition();)
{
nIndex = GetNextSelectedItem(pos);
DeleteItem(nIndex);
}

  POSITION GetFirstSelectedItemPosition() const

  如果函数执行成功,则返回条目的POSITION值,如果返回值为KULL,则表示当前列表视图控件中没有条目选中。


  Int GetNextSelectedItem(POSITION& pos) const

  如果函数执行成功,则返回列表视图控件中下一个被选中的条目索引。其中参数pos为将接收条目POSITION值的变量。

注意:使用这两个函数的时候 ListCtrl最好是有LVS_FULLROWSELECT的扩展风格。



在ListCtrl中进行排序
列表控件(CListCtrl)的顶部有一排按钮,用户可以通过选择不同的列来对记录进行排序。但是 CListCtrl并没有自动排序的功能,我们需要自己添加一个用于排序的回调函数来比较两个数据的大小,此外还需要响应排序按钮被点击的消息。下面讲述一下具体的做法。

CListCtrl提供了用于排序的函数,函数原型为:BOOLCListCtrl::SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData )。其中第一个参数为全局排序函数的地址,第二个参数为用户数据,你可以根据你的需要传递一个数据或是指针。该函数返回-1代表第一项排应在第二项前面,返回1代表第一项排应在第二项后面,返回0代表两项相等。

用于排序的函数原形为:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAMlParamSort),其中第三个参数为调用者传递的数据(即调用SortItems时的第二个参数dwData)。第一和第二个参数为用于比较的两项的ItemData,你可以通过DWORD CListCtrl::GetItemData( int nItem )/BOOLCListCtrl::SetItemData( int nItem, DWORD dwData )来对每一项的ItemData进行存取。在添加项时选用特定的CListCtrl::InsertItem也可以设置该值。由于你在排序时只能通过该值来确定项的位置所以你应该比较明确的确定该值的含义。

最后一点,我们需要知道什么时候需要排序,实现这点可以在父窗口中对LVN_COLUMNCLICK消息进行处理来实现。

下面我们看一个例子,这个例子是一个派生类,并支持顺序/倒序两种方式排序。为了简单我对全局数据进行排序,而在实际应用中会有多组需要排序的数据,所以需要通过传递参数的方式来告诉派序函数需要对什么数据进行排序。


//全局数据
struct DEMO_DATA
{
 char szName[20];
 int iAge;
}strAllData[5]={{"王某",30},{"张某",40},{"武某",32},{"陈某",20},{"李某",36}};

//CListCtrl派生类定义
class CSortList : public CListCtrl
{
// Construction
public:
 CSortList();
 BOOL m_fAsc;//是否顺序排序
 int m_nSortedCol;//当前排序的列
protected:
 //{{AFX_MSG(CSortList)
 //}}AFX_MSG
...
};

//父窗口中包含该CListCtrl派生类对象
class CSort_in_list_ctrlDlg : public CDialog
{
// Construction
public:
 CSort_in_list_ctrlDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data
 //{{AFX_DATA(CSort_in_list_ctrlDlg)
 enum { IDD = IDD_SORT_IN_LIST_CTRL_DIALOG };
 CSortList m_listTest;
 //}}AFX_DATA
}

//在父窗口中定义LVN_COLUMNCLICK消息映射
BEGIN_MESSAGE_MAP(CSort_in_list_ctrlDlg, CDialog)
 //{{AFX_MSG_MAP(CSort_in_list_ctrlDlg)
 ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST1, OnColumnclickList1)
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//初始化数据
BOOL CSort_in_list_ctrlDlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 //初始化ListCtrl中数据列表
 m_listTest.InsertColumn(0,"姓名");
 m_listTest.InsertColumn(1,"年龄");
 m_listTest.SetColumnWidth(0,80);
 m_listTest.SetColumnWidth(1,80);
 for(int i=0;i<5;i++)
 {
  m_listTest.InsertItem(i,strAllData[i].szName);
  char szAge[10];
  sprintf(szAge,"%d",strAllData[i].iAge);
  m_listTest.SetItemText(i,1,szAge);
  //设置每项的ItemData为数组中数据的索引
  //在排序函数中通过该ItemData来确定数据
  m_listTest.SetItemData(i,i);
 }
 return TRUE;  // return TRUE  unless you set the focus to acontrol
}

//处理消息
void CSort_in_list_ctrlDlg::OnColumnclickList1(NMHDR* pNMHDR, LRESULT* pResult) 
{
 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
 //设置排序方式
 if( pNMListView->iSubItem == m_listTest.m_nSortedCol )
  m_listTest.m_fAsc = !m_listTest.m_fAsc;
 else
 {
  m_listTest.m_fAsc = TRUE;
  m_listTest.m_nSortedCol = pNMListView->iSubItem;
 }
 //调用排序函数
 m_listTest.SortItems( ListCompare, (DWORD)&m_listTest);        
 *pResult = 0;
}

//排序函数实现
int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
 //通过传递的参数来得到CSortList对象指针,从而得到排序方式
 CSortList* pV=(CSortList*)lParamSort;
 
 //通过ItemData来确定数据
 DEMO_DATA* pInfo1=strAllData+lParam1;
 DEMO_DATA* pInfo2=strAllData+lParam2;
 CString szComp1,szComp2;
 int iCompRes;
 switch(pV->m_nSortedCol)
 {
 case(0):
  //以第一列为根据排序
  szComp1=pInfo1->szName;
  szComp2=pInfo2->szName;
  iCompRes=szComp1.Compare(szComp2);
  break;
 case(1):
  //以第二列为根据排序
  if(pInfo1->iAge == pInfo2->iAge)
   iCompRes = 0;
  else
   iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;
  break;
 default:
  ASSERT(0);
  break;
 }
 //根据当前的排序方式进行调整
 if(pV->m_fAsc)
  return iCompRes;
 else
  return iCompRes*-1;
}

排序最快:
CListCtrl::SortItems
Example

// Sort the item in reverse alphabetical order.
static int CALLBACK 
MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
  // lParamSort contains a pointer to the list view control.
  // The lParam of an item is just its index.
  CListCtrl* pListCtrl = (CListCtrl*) lParamSort;
  CString    strItem1 = pListCtrl->GetItemText(lParam1,0);
  CString    strItem2 = pListCtrl->GetItemText(lParam2,0);

  return strcmp(strItem2, strItem1);
}

void snip_CListCtrl_SortItems()
{
  // The pointer to my list view control.
  extern CListCtrl* pmyListCtrl;

  // Sort the list view items using my callback procedure.
  pmyListCtrl->SortItems(MyCompareProc, (LPARAM) pmyListCtrl);
}


If you don’t want to allow the users to sort the list byclicking on the header, you can use the style LVS_NOSORTHEADER. However, if youdo want to allow sorting, you do not specify the LVS_NOSORTHEADER. The control,though, does not sort the items. You have to handle the HDN_ITEMCLICKnotification from the header control and process it appropriately. In the codebelow, we have used the sorting function SortTextItems() developed in a previoussection. You may choose to sort the items in a different manner. 
Step 1: Add two member variables
Add two member variables to the CListCtrl. The first variable to track whichcolumn has been sorted on, if any. The second variable to track if the sort is ascendingor descending. 
        int nSortedCol; 
        BOOL bSortAscending; 
 

Step 2: Initialize them in the constructor.
Initialize nSortedCol to -1 to indicate that no column has been sorted on. Ifthe list is initially sorted, then this variable should reflect that. 
  
        nSortedCol = -1; 
        bSortAscending = TRUE; 
  
Step 3: Add entry in message map to handle HDN_ITEMCLICK
Actually you need to add two entries. For HDN_ITEMCLICKA and HDN_ITEMCLICKW. Donot use the class wizard to add the entry. For one, you need to add two entrieswhereas the class wizard will allow you only one. Secondly, the class wizarduses the wrong macro in the entry. It uses ON_NOTIFY_REFLECT() instead ofON_NOTIFY(). Since the HDN_ITEMCLICK is a notification from the header controlto the list view control, it is a direct notification and not a reflected one. 
ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked) 
ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
 Note that we specify the same function for both the notification.Actually the program will receive one or the other and not both. Whatnotification it receives will depend on the OS. The list view control onWindows 95 will send the ANSI version and the control on NT will send theUNICODE version. 
Also, note that the second argument is zero. This value filters for the id ofthe control and we know that header control id is zero.

Step 4: Write the OnHeaderClicked() function
Here’s where you decide what to do when the userclicks on a column header. The expected behaviour is to sort the list based onthe values of the items in that column. In this function we have used theSortTextItems() function developed in a previous section. If any of the columnsdisplays numeric or date values, then you would have to provide custom sortingfor them. 
  
void CMyListCtrl::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult) 
{
        HD_NOTIFY *phdn = (HD_NOTIFY *)pNMHDR;

        if( phdn->iButton ==0 )
        {
               // User clicked on header using left mouse button
               if( phdn->iItem == nSortedCol )
                       bSortAscending = !bSortAscending;
               else
                       bSortAscending = TRUE;

               nSortedCol = phdn->iItem;
               SortTextItems( nSortedCol, bSortAscending );

        }
        *pResult = 0;
}

让CListCtrl的SubItem也具有编辑功能:
要重载一个文本框,然后在LVN_BEGINLABELEDIT时改变文本框位置。
CInEdit m_InEdit;

    if( ( GetStyle() & LVS_TYPEMASK ) ==LVS_REPORT && ( m_nEditSubItem != 0 ) )
    {
        HWND    hwndEdit;
        CRect    rtBound;
        CString strText;

        hwndEdit =(HWND)SendMessage( LVM_GETEDITCONTROL );
        GetSubItemRect(pDispInfo->item.iItem, m_nEditSubItem, LVIR_LABEL, rtBound );
        m_InEdit.SubclassWindow( hwndEdit );
        m_InEdit.m_left = rtBound.left;
        strText = GetItemText(pDispInfo->item.iItem, m_nEditSubItem );
        m_InEdit.SetWindowText( strText );
    }

void CInEdit::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) 
{
    CRect rtClient;

    lpwndpos->x = m_left;  // m_left在LVN_BEGINLABELEDIT中设置

    CEdit::OnWindowPosChanging(lpwndpos);
    
    // TODO: Add your message handler code here
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值