List Control总结

来源:互联网 发布:幂法求矩阵特征值例子 编辑:程序博客网 时间:2024/04/29 22:07
1.新建对话框MFC,在对话框上放一个ListCtrl
ID:IDC_PATH
View:Report
2.为ListCtrl添加变量
右击->添加变量m_wndPath
3.找到OnInitDialog()函数添加如下代码:
[cpp] view plain copy
  1.   
[cpp] view plain copy
  1. // TODO: 在此添加额外的初始化代码  
  2.   
  3. m_wndPath.DeleteAllItems();//清空  
  4. m_wndPath.InsertColumn(0,_T("项目"));//添加列  
  5. m_wndPath.InsertColumn(1,_T("所在路径"));  
  6. m_wndPath.SetColumnWidth(0, 150);//设置列宽  
  7. m_wndPath.SetColumnWidth(1, 350);  
  8. m_wndPath.SetRedraw(FALSE);//防止重绘  
  9.   
  10. int nIndex;  
  11. //char|TCHAR项目属性->字符集:使用多字节字符集  
  12. TCHAR Path[MAX_PATH+1];//TCHAR取代char  MAX_PATH最长路径  
  13. nIndex=m_wndPath.InsertItem( 0,_T("Windows目录") );  
  14. if( nIndex < 0 ) return TRUE;  
  15. GetWindowsDirectory(Path,MAX_PATH);//取得windows目录  
  16. m_wndPath.SetItemText( nIndex, 1, Path );  
  17.   
  18. LPITEMIDLIST pidl;//桌面CSIDL_DESKTOPDIRECTORY  
  19. //用来得到系统的某些特定文件夹的位置信息  
  20. if(SUCCEEDED(SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOPDIRECTORY,&pidl)))  
  21. {  
  22.     if(SHGetPathFromIDList(pidl, Path))//功能是把项目标志符列表转换为文档系统路径  
  23.     {  
  24.         nIndex=m_wndPath.InsertItem( 0,_T("桌面"));//成功则返回0  
  25.         if( nIndex < 0 )  
  26.         {  
  27.             return TRUE;  
  28.         }  
  29.         m_wndPath.SetItemText( nIndex, 1, Path );  
  30.     }  
  31. }  
  32.   
  33. m_wndPath.SetRedraw(TRUE);//显示  
  34.   
  35. return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  

复制代码
4.char被TCHAR取代,若要用则:
项目属性->字符集:使用多字节字符集

源码:http://pan.baidu.com/netdisk/singlepublic?fid=1057737_281109902
url:http://greatverve.cnblogs.com/archive/2012/08/12/vc-list-control.html 
参考代码:
[cpp] view plain copy
  1. m_wndPath.DeleteAllItems();  
  2. m_wndPath.InsertColumn(0,"项目");  
  3. m_wndPath.InsertColumn(1,"所在路径");  
  4. m_wndPath.SetColumnWidth(0, 150);  
  5. m_wndPath.SetColumnWidth(1, 350);  
  6. m_wndPath.SetRedraw(FALSE);  
  7.   
  8. int nIndex;  
  9. const int nFolder[]={ CSIDL_ALTSTARTUP,CSIDL_APPDATA,CSIDL_BITBUCKET,CSIDL_COMMON_ALTSTARTUP,  
  10.     CSIDL_COMMON_DESKTOPDIRECTORY,CSIDL_COMMON_FAVORITES,CSIDL_COMMON_PROGRAMS,  
  11.     CSIDL_COMMON_STARTMENU,CSIDL_COMMON_STARTUP,CSIDL_CONTROLS,CSIDL_COOKIES,  
  12.     CSIDL_DESKTOP,CSIDL_DESKTOPDIRECTORY,CSIDL_DRIVES,CSIDL_FAVORITES,CSIDL_FONTS,  
  13.     CSIDL_HISTORY,CSIDL_INTERNET,CSIDL_INTERNET_CACHE,CSIDL_NETHOOD,CSIDL_NETWORK,  
  14.     CSIDL_PERSONAL,CSIDL_PRINTERS,CSIDL_PRINTHOOD,CSIDL_PROGRAMS,CSIDL_RECENT,  
  15.     CSIDL_SENDTO,CSIDL_STARTMENU,CSIDL_STARTUP,CSIDL_TEMPLATES };  
  16. const CString strFolderName[]={ "CSIDL_ALTSTARTUP","CSIDL_APPDATA","回收站","CSIDL_COMMON_ALTSTARTUP",  
  17.     "CSIDL_COMMON_DESKTOPDIRECTORY","CSIDL_COMMON_FAVORITES","CSIDL_COMMON_PROGRAMS",  
  18.     "CSIDL_COMMON_STARTMENU","CSIDL_COMMON_STARTUP","控制面板","CSIDL_COOKIES",  
  19.     "CSIDL_DESKTOP","桌面","我的电脑","收藏夹","字体",  
  20.     "历史纪录","CSIDL_INTERNET","CSIDL_INTERNET_CACHE","网上邻居","CSIDL_NETWORK",  
  21.     "我的文档","打印机","CSIDL_PRINTHOOD","程序组","最近打开的文档",  
  22.     "发送","任务条启动菜单目录","启动目录","临时文档" };  
  23.   
  24. char Path[MAX_PATH+1];  
  25. nIndex=m_wndPath.InsertItem( 0,"Windows目录" );  
  26. if( nIndex < 0 ) return TRUE;  
  27. GetWindowsDirectory(Path,MAX_PATH);  
  28. m_wndPath.SetItemText( nIndex, 1, Path );  
  29.   
  30. nIndex=m_wndPath.InsertItem( 0,"System目录" );  
  31. if( nIndex < 0 ) return TRUE;  
  32. GetSystemDirectory(Path,MAX_PATH);  
  33. m_wndPath.SetItemText( nIndex, 1, Path );  
  34.   
  35. int i,count=sizeof(nFolder)/sizeof(int);  
  36. for(i=0;i<count;i++)  
  37. {  
  38.     LPITEMIDLIST pidl;  
  39.     LPMALLOC pShellMalloc;  
  40.   
  41.     if(SUCCEEDED(SHGetMalloc(&pShellMalloc)))  
  42.     {  
  43.         if(SUCCEEDED(SHGetSpecialFolderLocation(NULL,  
  44.             nFolder[i],&pidl)))  
  45.         {  
  46.             if(SHGetPathFromIDList(pidl, Path))  
  47.             {  
  48.                 nIndex=m_wndPath.InsertItem( 0,strFolderName[i] );  
  49.                 if( nIndex < 0 )  
  50.                 {  
  51.                     pShellMalloc->Free(pidl);  
  52.                     pShellMalloc->Release();  
  53.                     return TRUE;  
  54.                 }  
  55.                 m_wndPath.SetItemText( nIndex, 1, Path );  
  56.             }  
  57.             pShellMalloc->Free(pidl);  
  58.         }  
  59.         pShellMalloc->Release();  
  60.     }  
  61. }  
  62. m_wndPath.SetRedraw(TRUE);  

复制代码
VC中ListCtrl经验总结
先注明一下,这里,我们用m_listctrl来表示一个CListCtrl的类对象,然后这里我们的ListCtrl都是report形式,至于其他的如什么大图标,小图标的暂时不讲,毕竟report是大众话的使用。其次,我们这里用条款一,条款二来描述第一点,第二点,这个是参照《Effective C++》的叫法,俺觉得这么叫比较COOL :)

条款一:设置ListCtrl的风格

在CSDN上常常看到有人问怎么设置风格的,他们ListCtrl的样子是一个列表,有横条和竖条分界线,然后选中一行,要整一行都选中,而不是只有某一列被选中,等等,这里给一个比较全面的设置方法。

//获得原有风格
DWORD dwStyle = ::GetWindowLong(m_listctrl.m_hWnd, GWL_STYLE); 
dwStyle &= ~(LVS_TYPEMASK);
dwStyle &= ~(LVS_EDITLABELS);
//设置新风格
SetWindowLong(m_listctrl.m_hWnd, GWL_STYLE,dwStyle, |LVS_REPORT | LVS_NOLABELWRAP | LVS_SHOWSELALWAYS);
//设置扩展风格
DWORD styles = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_CHECKBOXES;
ListView_SetExtendedListViewStyleEx(m_listctrl.m_hWnd, styles, styles );

其中LVS_EX_FULLROWSELECT 就是前面说得整行选中
LVS_EX_GRIDLINES 网格线(只适用与report风格的listctrl)
LVS_EX_CHECKBOXES 前面加个checkbox
pListCtrl->SetExtendedStyle( m_listctrl.GetExtendedStyle() | LVS_EX_SUBITEMIMAGES);

这也是一个很重要的属性,这样的话,可以在列表中加ICON,记得windows的任务管理器吗,你想做得那样,这个属性也要加哦,这个我以后会讲的~

条款二:加入列头

这是一个比较实质的东西,给列表框分列,然后加上列头,代码说话,来了
[cpp] view plain copy
  1. TCHAR rgtsz[2][10] = {_T("列头1"), _T("列头2")};  
  2. LV_COLUMN lvcolumn;  
  3. CRect rect;  
  4. m_listctrl.GetWindowRect(&rect);  
  5. for(int i=0;i<2;i++)  
  6. {  
  7.  lvcolumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH | LVCF_ORDER;  
  8.  lvcolumn.fmt = LVCFMT_LEFT;  
  9.  lvcolumn.pszText = rgtsz[i];  
  10.  lvcolumn.iSubItem = i;  
  11.  lvcolumn.iOrder = i;  
  12.  if(i==0)  
  13.  {  
  14.        lvcolumn.cx = rect.Width()*3/5 ;   
  15.  }  
  16.  else  
  17.        lvcolumn.cx = rect.Width()*2/5;  
  18.   
  19.     m_listctrl.InsertColumn(i, &lvcolumn);  
  20. }  


这是插入两列的做法,你要插入20列??随便你,依样画葫芦~~
lvcolumn.mask 中那个mask可以有各种属性,具体去看msdn吧,

条款三:把记录,插入列表框中

[cpp] view plain copy
  1. int nIndex = m_listctrl.GetItemCount();  
  2. LV_ITEM   lvitemAdd = {0};  
  3. lvitemAdd.mask = LVIF_TEXT;  
  4. lvitemAdd.iItem = nIndex ;  
  5. lvitemAdd.iSubItem = 0;  
  6. lvitemAdd.pszText =_T("毛毛1");;  
  7.   
  8. if (m_listctrl.InsertItem(&lvitemAdd) != -1)  
  9. {   
  10.    LV_ITEM lvitem = {0};  
  11.    lvitem.mask = LVIF_TEXT;  
  12.    lvitem.iItem = nIndex ;  
  13.    lvitem.iSubItem = 1;  
  14.   
  15.    lvitem.pszText =_T("毛毛2");  
  16.    m_listctrl.SetItem(&lvitem);     
  17. }  

nIndex 是当前的行数,然后把新的一行,插在最下面,

条款四:给列表中插入图标

在report格式中,也能插入图标
继续代码说话

m_image是个CImageList对象
m_image.Create(16,16, TRUE|ILC_COLOR24, 3, 1);
m_listctrl.SetImageList(&m_image,LVSIL_SMALL);

然后调用CImageList的成员函数int CImageList::Add( HICON hIcon );
把ICON插入到imagelist,
然后在插入记录的时候

lvitemAdd.mask = LVIF_TEXT; 
lvitemAdd.mask = LVIF_TEXT|LVIF_IMAGE

然后添加一个lvitemAdd.iImage = n;
这个n是imagelist中的序号,表示是具体的哪一个图标,list么,呵呵

条款五:插入记录时使用额外的信息,lParam 的使用

有时候,你想对于某一行,加入一些额外的信息,那么就可以使用这个lParam
msdn是这么描述的Specifies the 32-bit value of the item
我上次是为了在某一行加入一个信息,窗口句柄,然后是这么加的,

[cpp] view plain copy
  1. int nIndex = m_listctrl.GetItemCount();  
  2. LV_ITEM   lvitemAdd = {0};  
  3. lvitemAdd.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;  
  4. lvitemAdd.iItem = nIndex ;  
  5. lvitemAdd.iSubItem = 0;  
  6. lvitemAdd.pszText =_T("毛毛1");;  
  7. lvitemAdd.iImage = n;  
  8. lvitemAdd.lParam = (LPARAM)hwnd;(某个窗口的窗口句柄)  
  9.   
  10. if (m_listctrl.InsertItem(&lvitemAdd) != -1)  
  11. {   
  12.    LV_ITEM lvitem = {0};  
  13.    lvitem.mask = LVIF_TEXT;  
  14.    lvitem.iItem = nIndex ;  
  15.    lvitem.iSubItem = 1;  
  16.   
  17.    lvitem.pszText =_T("毛毛2");  
  18.    m_listctrl.SetItem(&lvitem);     
  19. }  

ok,这是一个比较全的例子的,又插ICON,又使用PARAM的

条款六 : 点击列表框,获取选中行信息

响应NM_CLICK消息,如果你有MSDN,可以看到,有专门关于listview的NM_CLICK的介绍

[cpp] view plain copy
  1. void CMyDlg::OnItemClick(NMHDR* pNMHDR, LRESULT* pResult)   
  2. {  
  3.    // TODO: Add your control notification handler code here  
  4.    int nItem = -1;  
  5.   
  6.    LPNMITEMACTIVATE lpNMItemActivate = (LPNMITEMACTIVATE)pNMHDR;  
  7.    if(lpNMItemActivate != NULL)  
  8.    {  
  9.       nItem = lpNMItemActivate->iItem;  
  10.    }  
  11. }  

现在nItem就是点击选中那行的index了,有了index,获取那行的信息还难吗
懒汉说:难,因为你还没讲,晕,那就继续说

条款七: 根据行的index,获取该行的信息

直接上代码吧

[cpp] view plain copy
  1. LV_ITEM lvitem = {0};  
  2. lvitem.iItem = nIndex;  
  3. lvitem.iSubItem = 0;  
  4. lvitem.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;  
  5. m_listctrl.GetItem(&lvitem)  


这样,就把nindex,第一列的信息取出来了,包括刚才我们加入的ICON,和那个额外信息(窗口句柄),比如我要获取窗口句柄,就可以hwnd = (HWND)lvitem.lParam;
mask 用来指明你想获取那些信息
具体可以查msdn中LVITEM Structure的定义和CListCtrl::GetItem

条款八:用程序选中某一行,使之选中

选中之 
m_listctrl.SetItemState(nIndex,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
不选中,取消选中之
m_listctrl.SetItemState(nIndex,0,LVIS_SELECTED|LVIS_FOCUSED);

条款九:获取当前所有选中的行(多选)

这个,俺就比较懒了,抄msdn的代码吧,反正很简单

[cpp] view plain copy
  1. // CListCtrl* pListCtrl = (CListCtrl*) GetDlgItem  
  2. (IDC_YOURLISTCONTROL);  
  3. ASSERT(pListCtrl != NULL);  
  4. POSITION pos = pList->GetFirstSelectedItemPosition();  
  5. if (pos == NULL)  
  6.    TRACE0("No items were selected!\n");  
  7. else  
  8. {  
  9.    while (pos)  
  10.    {  
  11.       int nItem = pList->GetNextSelectedItem(pos);  
  12.       TRACE1("Item %d was selected!\n", nItem);  
  13.       // you could do your own processing on nItem here  
  14.    }  
  15. }  
  16.   
  17.   
  18. 条款十:删除条款九中选中的行  
  19.   
  20. 这个相对前面九个条款是比较麻烦的,因为如果你要删除多行的话,往往要出错。比如,我现在要删除第0行和第1行(列表的行序列是从0开始的)  
  21. 那么好啊。我来删了  
  22.   
  23. m_listctrl.DeleteItem(0)  
  24. m_listctrl.DeleteItem(1)  
  25.   
  26. 恭喜你,错了,我好开心啊 :)  
  27. 因为你删除第0行以后,下面的行会往上移,那么原来的第1行就变成了第0行,那么你再 m_listctrl.DeleteItem(1),那么删除的是原来的第2行,真麻烦,  
  28. 所以,只有从下往上删,才是安全的,先删的,不会影响后面的操作,  
  29.   
  30. m_listctrl.DeleteItem(1)  
  31. m_listctrl.DeleteItem(0)  
  32.   
  33. 但有时候,我们也不知道要删除哪些行,只知道要删除选中的那些行,像条款九中的那些  
  34. 如果我们还是用  
  35.   
  36. POSITION pos = m_listctrl.GetFirstSelectedItemPosition();  
  37. if (pos == NULL)  
  38.    TRACE0("No items were selected!\n");  
  39. else  
  40. {  
  41.    while (pos)  
  42.    {  
  43.       int nItem = m_listctrl.GetNextSelectedItem(pos);  
  44.       m_listctrl.DeleteItem(nItem );  

   }
}

你就等着收尸吧
这时候我们就要B4微软了,为虾米木有GetLastselectedItemPosition 和GetPrevSelectedItem,多写一对成员函数会死啊 :(
没办法,办法自己想,这里有个笨办法

POSITION sSelPos = NULL;
while(sSelPos = m_listctrl.GetFirstSelectedItemPosition())
{
   int nSelItem = -1;
   nSelItem = m_listctrl.GetNextSelectedItem(sSelPos);
   if(nSelItem >= 0 && nSelItem<m_listctrl.GetItemCount())
   {
      //好了,这个nSelItem 就是我们要的DD
   }
}

GetNextSelectedItem这个函数,看msdn的用法,其实是返回第一个的index,然后走到下一个选中的行去,所以这么做也是安全的,在实际中,俺也是这么做的,测试也通过,没问题的
当然,还有个办法,先通过GetFirstSelectedItemPosition和GetNextSelectedItem来获取所有的选中行的index,然后把这些index放到一个数组里,然后再从下往上删
唉真麻烦啊,还要不定数组,不说用new在堆上开吧,那么一个vector总是要的吧,麻烦啊,所以我暂时是用上述的办法来删除,也供大家参考,希望能找到更好的办法。
VC编程技术点滴(六)使用ListControl控件显示数据表 
http://blog.sina.com.cn/s/blog_5f30147a0100dzgx.html 

0 0
原创粉丝点击