ListCtrl由四种风格的实现:
Icons,使用32*32大小的图标显示列表。
Small Icons,使用16*16大小的图标显示一个单一列的列表。
List,使用Small Icons,可有多列,第二列必须填充之前必须填充第一列,自上而下排序。
Report,编程者自定义的格式显示列表。
创建一个“基于对话框”的MFC应用程序,命名为ListCtrl。
(1)创建ListCtrl
一般来说ListCtrl控件的创建都是直接拖拽工具箱中的控件完成的。如果要用代码实现,则应该在ListCtrlDlg.cpp中的OnInitDialog()函数中实现。一般对ListCtrl的属性的更改也应该在此函数中。
CListCtrl *lstCtrl = new CListCtrl;
lstCtrl->Create(WS_CHILD | WS_VISIBLE,CRect(10, 10, 320, 280), this, 0x285);
为了防止内存泄露,正确的做法是,在ListCtrlDlg.h头文件中添加变量m_ListCtrl,在OnInitDialog中new,最后在析构函数中Delete。
(2)ListCtrl风格
ListCtrl的风格可以在List的View属性中更改。
图1.Icon风格LVS_ICON
图2.Small Icon风格:LVS_SMALLICON
图3.List风格:LVS_LIST
图4.Report风格:LVS_REPORT
(3)ListCtrl扩展风格
调用CListCtrl::SetExtendStyle()方法可以为ListCtrl设置扩展风格,语法为:
DWORD SetExtendedStyle(DWORD dwNewStyle);
参数值有:
LVS_EX_CHECKBOXES:在最左侧显示选择框(check box)
LVS_EX_FULLROWSELECT:这种风格允许Report View的整行来被选择而不是仅仅一项
LVS_EX_TRACKSELECT:当设置这种风格的时候,用户可以隔项选取
LVS_SINGLESEL:禁止用户一次选择多项
LVS_SHOWSELALWAYS:ListCtrl在失去焦点时,已选择的项仍处于选中状态
LVS_EX_GRIDLINES:显示网格
设置扩展风格,可以先创建一个DWORD变量,然后对变量赋值。如果想用多种风格,可以用|操作。
注:listview的style请查阅msdn
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceshellui5/html/wce50lrflistviewstyles.asp
(1) 添加List的项
调用CListCtrl::InsertItem()方法来为List添加该有的项。
声明如下:int InsertItem(const LVITEM* pItem);
注:此方法适用于ListCtrl风格为List时,风格为Report则无法显示数据。
此方法需要用到一个LVITEM的指针,LVITEM为一个结构体,其中比较重要的参数有:
mask:用来指定你像个当前项设置的类型。
iItem:指定项的索引,第一个item应该为0,第二个item为1等等
iSumItem:当前值的的子项,如果当前项是主导项,iSumItem应该存储从0开始的数组
pszText:要显示项的字符串
cchTextMask:指定文本的长度
使用上述方法,为List添加一项:(m_StoreItems为ListCtrl变量)
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = _T("Sandra C. Anschwitz");
m_StoreItems.InsertItem(&lvItem);
但是我们平时经常用的InsertItem方法为:
int InsertItem(int nItem, LPCTSTR lpszItem);
如果选择ListCtrl的风格为Report,那么在添加项之前,要先创建列。
我们可以使用CListCtrl::InsertColumn()方法,
(1)它的一种声明为:
int InsertColumn(int nCol, const LVCOLUMN* pColumn);
nCol:是要创建的列的索引
pColumn:是指向LVCOLUMN结构的一个指针
typedef struct _LVCOLUMN {
UINT mask;
int fmt;
int cx;
LPTSTR pszText;
int cchTextMax;
int iSubItem;
#if (_WIN32_IE >= 0x0300)
int iImage;
int iOrder;
#endif
} LVCOLUMN, FAR *LPLVCOLUMN;
mask: 指定你创建的列的属性。
fmt: 格式化的文本。例如,你可以选择左对齐(默认值LVCFMT_LEFT),居中(LVCFMT_CENTER),右对齐。如果你想为这个值设置一个值,那么在初始化mask变量的时候增加LVCF_FMT属性。
cx: 用来指定列文本的宽度。如果未初始化,他的长度将被设定为刚好能显示文本的长度。除非你有特别好的理由省略它,一般要对其进行初始化。如果打算初始化此值,给mask增加LVCF_WIDTH属性。
pszText: 指定创建列的表头。除了第一列,此变量不是必须初始化的。要想初始化此变量,在mask增加LVCF_TEXT属性。
cchTextMax:指定表头的长度。
添加一列的代码:
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);
(2) CListCtrl::InsertColumn()的另一种声明为
int InsertColumn(int nCol,LPCTSTR lpszColumnHeading,int nFormat = LVCFMT_LEFT,
int nWidth = -1,int nSubItem = -1);
nCol:列的索引。
lpszColumnHeading:表头标题显示的字符
nFormat:表头文字的对齐方式。默认为左对齐(LVCFMT_LEFT).
wWidth:以像素为单位设置列的宽度。
nSubItem:设置当前列子项的索引。-1时表示没有子项与此列相关。
InsertColumn()方法返回一个整形值来标识你增加的列。
然后通过调用CListCtrl::SetItemText()方法来为此列添加具体的字符串。
BOOL SetItemText(int nItem, int nSubItem, LPTSTR lpszText);
nItem:第几行
nSubItem:第几列
lpszText:字符串信息
//首先定义列,此处定义了三列
LVCOLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 120;
lvColumn.pszText = TEXT("Full Name");
m_StoreItems.InsertColumn(0, &lvColumn);
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 100;
lvColumn.pszText = TEXT("Profession");
m_StoreItems.InsertColumn(1, &lvColumn);
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 80;
lvColumn.pszText = TEXT("Fav Sport");
m_StoreItems.InsertColumn(2, &lvColumn);
//然后添加一行
LVITEM lvItem;
int nItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = TEXT("Sandra C. Anschwitz");
nItem = m_StoreItems.InsertItem(&lvItem);
//添加此行的子项,与上边定义的列数相对应
m_StoreItems.SetItemText(nItem, 1, TEXT("Singer"));
m_StoreItems.SetItemText(nItem, 2, TEXT("HandBall"));
首先通过GetWindowLong()获得当前控件的风格,在将返回值与LVS_TYOEMASK的反进行&操作,这样返回值就会被清零。然后将返回值与要改变的风格进行|操作,最后使用SetWindowLong()重新设置控件风格即可。
LONG mListStyle = ::GetWindowLong(m_List.m_hWnd, GWL_STYLE);
mListStyle &= ~LVS_TYPEMASK;
mListStyle |= LVS_ICON;
::SetWindowLong(m_List.m_hWnd, GWL_STYLE, mListStyle);
如果想在表头上添加一副位图,你要先声明一个CImageList变量,并初始化。然后调用CListCtrl::SetImageList()方法,并为之传参。如果你这么做,并且你使用的是LVCOLUMN指针作为CListCtrl::InsertColumn()的参数,需要给mask参数添加LVCF_IMAGE的值,并为fmt添加LVCFMT_IMAGE的值。
实现代码:
LVCOLUMN lvColumn;
CImageList *ImgHeaders = new CImageList;
//参数16,16指明了在IDI_UP和IDI_LOSANGE中使用哪一个像素的图像。也可以改为32,32
ImgHeaders->Create(16, 16, ILC_MASK, 1, 1);
//将图标加载到ImageList中
ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_UP));
ImgHeaders->Add(AfxGetApp()->LoadIcon(IDI_LOSANGE));
//使用SetImageList将ImageList赋值给ListCtrl,这样ListCtrl就可以使用ImageList中的图标
m_List.SetImageList(ImgHeaders, LVSIL_SMALL);
//如果想要表头加载图标,就必须为mask和fmt赋值参数,并通过iImage来指定使用ImageList中的哪个图标
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_IMAGE;
lvColumn.fmt = LVCFMT_LEFT | LVCFMT_IMAGE;
lvColumn.cx = 120;
//参数指明使用第一个图标,这里的顺序与上边Add的顺序一样
lvColumn.pszText = "Full Name";
lvColumn.iImage = 0;
m_List.InsertColumn(0, &lvColumn);
//不添加图标则不用赋值
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 100;
lvColumn.pszText = "Profession";
m_List.InsertColumn(1, &lvColumn);
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_IMAGE;
lvColumn.fmt = LVCFMT_LEFT | LVCFMT_IMAGE;
lvColumn.iImage = 1;
lvColumn.cx = 80;
lvColumn.pszText = "Fav Sport";
m_List.InsertColumn(2, &lvColumn);
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 75;
lvColumn.pszText = "Hobby";
m_List.InsertColumn(3, &lvColumn);
与上面再表头显示图片类似。在第一列的最左端显示图片。
代码(接6的代码使用)
LVITEM lvItem;
int nItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.iImage = 0;
lvItem.pszText = _T(“你好”);
nItem = m_StoreItems.InsertItem(&lvItem);
m_StoreItems.SetItemText(nItem, 1, _T(“2”));
m_StoreItems.SetItemText(nItem, 2, _T(“3”));
m_StoreItems.SetItemText(nItem, 3, _T(“4”));
找到ListCtrl控件的属性,添加onNMClickList1单击事件响应函数。
函数原型:void OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult)
在函数中添加如下代码:
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
//如果单击的不是空白或分割线,就执行
if(pNMListView->iItem != -1)
{
CString strtemp("11");
//获取行号和列号
strtemp.Format(_T(“第%d行%d列”),pNMListView->iItem,pNMListView->iSubItem);
::AfxMessageBox(strtemp);
}
接上边8的代码:
m_List->DeleteItem(pNMListView->iItem);//传递参数为行号
ListCtrl追加位图图标
加载位图
CBitmap bmap;
bmap.LoadBitmap(IDB_BITMAP_LIST_ICON);
m_pImageList = new CImageList;
m_pImageList->Create( 20, 20, ILC_COLOR24, 11, 0 );
m_pImageList->Add( &bmap, (COLORREF)0 );
bmap.DeleteObject();
list.SetImageList( m_pImageList, LVSIL_SMALL );
//设置属性
//report型
long style = GetWindowLong(lc.m_hWnd,GWL_STYLE);
style |= (LVS_REPORT|LVS_SINGLESEL| LVS_ALIGNTOP |LVS_SHOWSELALWAYS );
SetWindowLong(lc.m_hWnd,GWL_STYLE,style);
//扩展属性
//网格化----行全选----列可以加位图
lc.SetExtendedStyle( LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT|LVS_EX_SUBITEMIMAGES );
lc.InsertItem( iRow,strItemText,getImage());
//第iColum列加位图
lc.SetItem( iRow,iColum,LVIF_IMAGE,_T(""),ICON_TIMER,0,0,0,0);