VC控件——ListControl

来源:互联网 发布:ubuntu apt get jdk 编辑:程序博客网 时间:2024/06/08 05:37

ListCtrl控件由四种列表的显示方式构成:

                         Icons: 控件显示项的列表,使用32*32(像素)大小的icons

                        Small Icons:和剩下的两项相似的想法,它使用16*16(像素)大小的图标来显示一个单一的列表项

                        List:这种列表,使用small icons,也是组织列;这种情况下,在第二列填充之前必须填充第一列

                        Report:安排项的目的是提供列表开发者的信息   

(1)      创建List Control

法1:列表初始化:

        添加变量m_list .create(WS_CHILD|WS_VISIBLE,CRect(10,10,320,280),this,0x285;

         创建控件的时候,增加LVS_ICON   LVS_SMALLICON  LVS_REPORT   LVS_REPORT等   

         除了常规的几种风格外,Win32类库为ListCtrl提供了扩展风格,提供了一个扩展风格,调用CListCtrl::SetExtendStyle()方法,它的语法为:

         DWORD SetExtendedStyle(DWORD dwNewStyle);

         LVS_ALIGNLEFT                        显示格式是大图标或小图标时,标签放在图标的左边
         LVS_ALIGNTOP                         显示格式是大图标或小图标时,标题放在图标的上边
         LVS_AUTOARRANGE                 显示格式是大图标或小图标时,自动排列控件中的列表项
         LVS_EDITLABELS                      用户可以修改标签文本
         LVS_ICON                                 指定大图标显示格式
         LVS_LIST                                  指定列表显示格式
         LVS_NOCOLUMNHEADER         在报表格式中不显示列的表头
         LVS_NOLABELWRAP                显示格式是大图标时,使标签文本单行显示。默认是多行显示
         LVS_NOSCROLL                       列表视图控件无滚动条,此风格不能与LVS_LIST或LVS_REPORT组合使用
         LVS_NOSORTHEADER              报表格式的列表视图控件的表头不能作为排序按钮使用
         LVS_OWNERDRAWFIXED        由控件的拥有者负责绘制表项
         LVS_REPORT                           指定报表显示格式
         LVS_SHAREIMAGELISTS           使列表视图共享图像序列
         LVS_SHOWSELALWAYS           即使控件失去输入焦点,仍显示出项的选择状态
         LVS_SINGLESEL                       指定只能有一个列表项被选中。默认时可以多项选择
         LVS_SMALLICON                      指定小图标显示格式
         LVS_SORTASCENDING             按升序排列列表项
         LVS_SORTDESCENDING          按降序排列列表项

            

         添加项(单元项):

          结构体:   typedefstruct {

UINT mask;用来指定你想给当前项设置的类型。
int iItem;指定改变项的索引,第一个item应该为0,第二个item为1等等。
int iSubItem;当前值的的子项,如果当前项是主导项,iSumItem应该存储从0开始的数组
UINT state;
UINT stateMask;
LPTSTR pszText; 要显示项的字符串,你可以通过cchTextMask指定文本的长度
int cchTextMax;
int iImage;
LPARAM lParam;
} LVITEM,*LPLVITEM;

lvItem.mask= LVIF_TEXT;
lvItem.iItem=0;

lvItem.iSubItem=0;

lvItem.pszText= strNumber;m_list.InsertItem(&lvItem);

LVITEM结构体的值将决定新项的功能。例如,一旦增加了一个项,你可能想要准备删除前面的项、剪切和粘贴操作,在这种情况下,你应该将设置为LVIS_CUT;如果你想实现拖放操作,你可以设置LVIS_DROPHILIGHTED;如果想让项获得焦点,设置LVIS_FOCUSED;包含LVIS_SELECTED属性的情况下可以被选中

创建一个ListCtrl的列

你可以使用CListCtrl::InsertColumn()方法,它的一种声明为:

int InsertColumn(int nCol, const LVCOLUMN* pColumn);

  nCol:将要创建列的索引

  pColumn:指向LVCOLUMN结构体指针,结构体定义如下:

typedefstruct _LVCOLUMN {
UINT mask;用来指定你想要的列的属性
int fmt;格式化列的文本(默认值LVCFMT_LEFT),居中(LVCFMT_CENTER),或者右对齐(LVCFMT_RIGHT)
int cx;cx 用来指定列文本的宽度
LPTSTR pszText;pszText 是将要显示的列的字符串
int cchTextMax;
int iSubItem;
} LVCOLUMN, FAR*LPLVCOLUMN;

LVCOLUMN lvColumn;

int nCol; 例如
lvColumn.mask= LVCF_FMT| LVCF_TEXT| LVCF_WIDTH;

lvColumn.fmt= LVCFMT_LEFT;

lvColumn.cx=120;

lvColumn.pszText= TEXT("Full Name");

nCol= m_StoreItems.InsertColumn(0,&lvColumn);

你也可以用CListCtrl::InsertColumn()方法的另一个版本,你可以用下面的版本,来为控件创建列:

int InsertColumn(int nCol,   列的索引,必须要指定的;
LPCTSTR lpszColumnHeading, 在列的开始要显示的字符串,和LVCOLUMN::pszText成员相似;

LPCTSTR lpszColumnHeading, 在列的开始要显示的字符串,和LVCOLUMN::pszText成员相似;

int nFormat= LVCFMT_LEFT,用来指定lpszColumnHeading的水平对齐方式。默认为左对齐(LVCFMT_LEFT),居中为

int nWidth=-1,以像素为单位来设定列的宽度,如果你不想指定它的大小,可设置为-1

int nSubItem=-1);用来设定当前列子项的索引。

int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat , int nWidth, int nSubItem)插入列。            nCol为列的位置,从零开始,lpszColumnHeading为显示的列名,nFormat为显示对齐方式, nWidth为显示宽度,nSubItem为分配给该列的列索引。 


成员函数:

 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); //设置扩展风格

插入数据
     m_list.InsertColumn( 0, "ID", LVCFMT_LEFT, 40 );//插入列
      m_list.InsertColumn( 1, "NAME", LVCFMT_LEFT, 50 );
      int nRow = m_list.InsertItem(0, “11”);//插入行
      m_list.SetItemText(nRow, 1, “jacky”);//设置数据
 
设置为Report属性后,若要ListControl显示为列表状,则在Init函数中,添加:
ListView_SetExtendedListViewStyle(m_listctrl.m_hWnd,LVS_EX_GRIDLINES|LVS_EX_ONECLICKACTIVATE|LVS_EX_FULLROWSELECT);
int InsertItem( int nItem, LPCTSTR lpszItem ); 插入行

nItem:指明插入位置

lpszItem:为显示字符。

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

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

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

lpszColumnHeading:为显示的列名

nFormat:为显示对齐方式

nWidth:为显示宽度

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


BOOL SetItemText( int nItem, int nSubItem, LPTSTR lpszText );设置每列的显示字符

nItem:为行位置

nSubItem:为列位置

lpszText:为显示字符


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

m_list.SetImageList(&m_listSmall,LVSIL_SMALL);//设置 ImageList

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")

总结:1. ListCtrl 风格

LVS_ICON: 为每个item显示大图标

LVS_SMALLICON: 为每个item显示小图标

LVS_LIST: 显示一列带有小图标的item

LVS_REPORT: 显示item详细资料

直观的理解:windows资源管理器,“查看”标签下的“大图标,小图标,列表,详细资料”

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

2. 设置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); //设置扩展风格

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

3. 插入数据

m_list.InsertColumn( 0, "ID", LVCFMT_LEFT, 40 );//插入列

m_list.InsertColumn( 1, "NAME", LVCFMT_LEFT, 50 );

int nRow = m_list.InsertItem(0, “11”);//插入行

m_list.SetItemText(nRow, 1, “jacky”);//设置数据

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

4. 一直选中item

选中style中的Show selection always,或者在上面第2点中设置LVS_SHOWSELALWAYS

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

5. 选中和取消选中一行

int nIndex = 0;

//选中

m_list.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);

//取消选中

m_list.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);


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

6. 得到listctrl中所有行的checkbox的状态

m_list.SetExtendedStyle(LVS_EX_CHECKBOXES);

CString str;

for(int i=0; i<m_list.GetItemCount(); i )

{

if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_list.GetCheck(i))

{

str.Format(_T("第%d行的checkbox为选中状态"), i);

AfxMessageBox(str);

}

}


CString strIns;

strIns="delete from tmpStatByGround";

m_pRs.CreateInstance(__uuidof(Recordset));

m_pRs->CursorLocation = adUseClient;

m_pRs->Open((LPCTSTR)strIns, vDispatch, adOpenKeyset,

adLockOptimistic, adCmdUnknown);


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

7. 得到listctrl中所有选中行的序号

方法一:

CString str;

for(int i=0; i<m_list.GetItemCount(); i )

{

if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED )

{

str.Format(_T("选中了第%d行"), i);

AfxMessageBox(str);

}

}

方法二:

POSITION pos = m_list.GetFirstSelectedItemPosition();

if (pos == NULL)

TRACE0("No items were selected!\n");

else

{

while (pos)

{

int nItem = m_list.GetNextSelectedItem(pos);

TRACE1("Item %d was selected!\n", nItem);

// you could do your own processing on nItem here

}

}

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

8. 得到item的信息

TCHAR szBuf[1024];

LVITEM lvi;

lvi.iItem = nItemIndex;

lvi.iSubItem = 0;

lvi.mask = LVIF_TEXT;

lvi.pszText = szBuf;

lvi.cchTextMax = 1024;

m_list.GetItem(&lvi);

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

9. 得到listctrl的所有列的header字符串内容

LVCOLUMN lvcol;

char str[256];

int nColNum;

CString strColumnName[4];//假如有4列

nColNum = 0;

lvcol.mask = LVCF_TEXT;

lvcol.pszText = str;

lvcol.cchTextMax = 256;

while(m_list.GetColumn(nColNum, &lvcol))

{

strColumnName[nColNum] = lvcol.pszText;

nColNum ;

}

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

10. 使listctrl中一项可见,即滚动滚动条

m_list.EnsureVisible(i, FALSE);

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

11. 得到listctrl列数

int nHeadNum = m_list.GetHeaderCtrl()->GetItemCount();

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

12. 删除所有列

方法一:

while ( m_list.DeleteColumn (0))

因为你删除了第一列后,后面的列会依次向上移动。

方法二:

int nColumns = 4;

for (int i=nColumns-1; i>=0; i--)

m_list.DeleteColumn (i);

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

13. 得到单击的listctrl的行列号

添加listctrl控件的NM_CLICK消息相应函数

void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)

{

// 方法一:

/*

DWORD dwPos = GetMessagePos();

CPoint point( LOWORD(dwPos), HIWORD(dwPos) );


m_list.ScreenToClient(&point);


LVHITTESTINFO lvinfo;

lvinfo.pt = point;

lvinfo.flags = LVHT_ABOVE;


int nItem = m_list.SubItemHitTest(&lvinfo);

if(nItem != -1)

{

CString strtemp;

strtemp.Format("单击的是第%d行第%d列", lvinfo.iItem, lvinfo.iSubItem);

AfxMessageBox(strtemp);

}

*/


// 方法二:

/*

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

if(pNMListView->iItem != -1)

{

CString strtemp;

strtemp.Format("单击的是第%d行第%d列",

pNMListView->iItem, pNMListView->iSubItem);

AfxMessageBox(strtemp);

}

*/

*pResult = 0;

}

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

14. 判断是否点击在listctrl的checkbox上

添加listctrl控件的NM_CLICK消息相应函数

void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)

{

DWORD dwPos = GetMessagePos();

CPoint point( LOWORD(dwPos), HIWORD(dwPos) );


m_list.ScreenToClient(&point);


LVHITTESTINFO lvinfo;

lvinfo.pt = point;

lvinfo.flags = LVHT_ABOVE;


UINT nFlag;

int nItem = m_list.HitTest(point, &nFlag);

//判断是否点在checkbox上

if(nFlag == LVHT_ONITEMSTATEICON)

{

AfxMessageBox("点在listctrl的checkbox上");

}

*pResult = 0;

}

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

15. 右键点击listctrl的item弹出菜单

添加listctrl控件的NM_RCLICK消息相应函数

void CTest6Dlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult)

{

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

if(pNMListView->iItem != -1)

{

DWORD dwPos = GetMessagePos();

CPoint point( LOWORD(dwPos), HIWORD(dwPos) );


CMenu menu;

VERIFY( menu.LoadMenu( IDR_MENU1 ) );

CMenu* popup = menu.GetSubMenu(0);

ASSERT( popup != NULL );

popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this );

}

*pResult = 0;

}

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

16. item切换焦点时(包括用键盘和鼠标切换item时),状态的一些变化顺序

添加listctrl控件的LVN_ITEMCHANGED消息相应函数

void CTest6Dlg::OnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult)

{

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

// TODO: Add your control notification handler code here


CString sTemp;


if((pNMListView->uOldState & LVIS_FOCUSED) == LVIS_FOCUSED &&

(pNMListView->uNewState & LVIS_FOCUSED) == 0)

{

sTemp.Format("%d losted focus",pNMListView->iItem);

}

else if((pNMListView->uOldState & LVIS_FOCUSED) == 0 &&

(pNMListView->uNewState & LVIS_FOCUSED) == LVIS_FOCUSED)

{

sTemp.Format("%d got focus",pNMListView->iItem);

}


if((pNMListView->uOldState & LVIS_SELECTED) == LVIS_SELECTED &&

(pNMListView->uNewState & LVIS_SELECTED) == 0)

{

sTemp.Format("%d losted selected",pNMListView->iItem);

}

else if((pNMListView->uOldState & LVIS_SELECTED) == 0 &&

(pNMListView->uNewState & LVIS_SELECTED) == LVIS_SELECTED)

{

sTemp.Format("%d got selected",pNMListView->iItem);

}


*pResult = 0;

}

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

17. listctrl的 subitem 添加图标

注意: 首先要用 InsertItem() 插入一行的第一列, 然后才能用 SetItem 设置其他项 

m_list.SetExtendedStyle(LVS_EX_SUBITEMIMAGES);

m_userlist.SetItem(..);

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

18. 在CListCtrl显示文件,并根据文件类型来显示图标

网上找到的代码,自己试用并改正过, share

步骤1: 设置 list 的图像列表为 系统图像列表 

BOOL SetSystemImageList( CListCtrl & list )

HIMAGELIST himlSmall;

HIMAGELIST himlLarge;

SHFILEINFO sfi;

char cSysDir[MAX_PATH];

CString strBuf;

memset(cSysDir, 0, MAX_PATH);

GetWindowsDirectory(cSysDir, MAX_PATH);

strBuf = cSysDir ;


// SHGetFileInfo:

// If uFlags contains SHGFI_SYSICONINDEX, the return value is a handle to

// an image list that contains the large icon images.

// If SHGFI_SMALLICON is included with SHGFI_SYSICONINDEX, the return value

// is the handle to an image list that contains the small icon images.

//

himlSmall = (HIMAGELIST)SHGetFileInfo ( (LPCSTR)cSysDir, 

0, 

&sfi,

sizeof(SHFILEINFO), 

SHGFI_SYSICONINDEX | SHGFI_SMALLICON );

himlLarge = (HIMAGELIST)SHGetFileInfo((LPCSTR)cSysDir, 

0, 

&sfi, 

sizeof(SHFILEINFO), 

SHGFI_SYSICONINDEX | SHGFI_LARGEICON);

if (himlSmall && himlLarge)

{

::SendMessage(list.m_hWnd, LVM_SETIMAGELIST,

(WPARAM)LVSIL_SMALL, (LPARAM)himlSmall);


::SendMessage(list.m_hWnd, LVM_SETIMAGELIST,

(WPARAM)LVSIL_NORMAL, (LPARAM)himlLarge);

}

return TRUE;

}

步骤2: 给列表添加指定的文件, 同时获得该文件的的图标索引, 给 list 添加图标

int GetIconIndex(LPCTSTR lpszPath, BOOL bIsDir, BOOL bSelected) ; // 向前声明

void AddFiles(CListCtrl & list, LPCTSTR lpszFileName, BOOL bAddToDocument)

{

int nIcon = GetIconIndex(lpszFileName, FALSE, TRUE);

CString strSize;

CFileFind filefind;

// get file size

if ( filefind.FindFile(lpszFileName))

{

filefind.FindNextFile();

strSize.Format("%d", filefind.GetLength());

}

else

strSize = "0";

// split path and filename

CString strFileName = lpszFileName;

CString strPath;

int nPos = strFileName.ReverseFind('\\');

if (nPos != -1)

{

strPath = strFileName.Left(nPos);

strFileName = strFileName.Mid(nPos 1);

}

// insert to list

int nItem = list.GetItemCount();


//list.InsertItem(nItem, strFileName, nIcon);

//list.SetItemText(nItem, 1, strSize);

//

// 此处可以根据实际需要修改代码

//

}


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

19. listctrl内容进行大数据量更新时,避免闪烁

m_list.SetRedraw(FALSE);

//更新内容

m_list.SetRedraw(TRUE);

m_list.Invalidate();

m_list.UpdateWindow();

20. 清除 ListCtrl 以重新初始化:

// 删除所有行

m_ctrllist.DeleteAllItems() ; 

// 删除所有列

int iColCount = m_ctrllist.GetHeaderCtrl()->GetItemCount() ;


// 方法 1

// 原理: 删除第一列后, 其他列向前移动

while( m_ctrllist.DeleteColumn(0) ) ;


// 方法 2

for (int i=0; i < iColCount ; i )

{

m_ctrllist.DeleteColumn(0);

}

// 方法 3

for (int i=iColCount-1; i >= 0; i-- )

{

m_ctrllist.DeleteColumn( i );

}











0 0
原创粉丝点击