赞
踩
咳咳,花了2天的时间,好好的把列表控件ListCtrl的基本使用研究了下。ListCtrl一共有4种样式:小图标、大图标、列表和报告。
其实呢,列表控件我们再熟悉不过了,因为当你随便打开一个文件夹的时候,显示的就是一个列表控件。不相信?那可以试着修改下查看方式,在查看方式中有小图标、大图标、列表和详细信息,分别对应的就是以上的4种样式。所以啊,列表控件使用到的地方其实是很多的。不过,我们在写程序的时候用到的最多的是report这种样式,也就是用来显示大量的数据用的。因此,在这篇文章里,主要就是介绍report样式的使用,前面的3种就不讲了。
1.首先说说ListCtrl最简单的使用,也就是数据的插入、删除等
先在XXXDlg.h头文件中为列表控件添加一个Control类型的变量
CListCtrl m_list1;
再在XXXDlg.cpp源文件中的OnInitDialog()函数中给m_list1设定一些信息
// ListCtrl1
m_list1.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); // 整行选择、网格线
m_list1.InsertColumn(0, _T(""), LVCFMT_LEFT, 0);
m_list1.InsertColumn(1, _T("姓名"), LVCFMT_LEFT, 100); // 插入第2列的列名
m_list1.InsertColumn(2, _T("年龄"), LVCFMT_LEFT, 100); // 插入第3列的列名
m_list1.InsertColumn(3, _T("性别"), LVCFMT_LEFT, 100); // 插入第4列的列名
for(int i = 0;i <= 7;i++) {
strName.Format(_T("小石头%d"), i);
strAge.Format(_T("%d"), 20 + i);
strSex = i % 2 ? _T("男") : _T("女");
m_list1.InsertItem(i, _T("")); // 插入行
m_list1.SetItemText(i, 1, strName); // 设置第2列(姓名)
m_list1.SetItemText(i, 2, strAge); // 设置第3列(年龄)
m_list1.SetItemText(i, 3, strSex); // 设置第4列(性别)
}
这里牵涉到几个函数SetExtendedStyle()、InsertColumn()、InsertItem()、SetItemText()。下面一一介绍
(1)SetExtendedStyle() 设置列表控件的扩展样式
这里介绍几个常用的扩展样式:
LVS_EX_CHECKBOXES每一行的最前面带个复选框
LVS_EX_FULLROWSELECT整行选中
LVS_EX_GRIDLINES网格线
LVS_EX_HEADERDRAGDROP列表头可以拖动
给个MSDN的地址,里面有更多的样式:http://msdn.microsoft.com/zh-cn/library/bb774732.aspx
(2)InsertColumn() 插入1列
int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1 )
nCol 第几列
lpszColumnHeading 列名
nFormat 对齐的方式,有3种:LVCFMT_LEFT(左对齐)、LVCFMT_CENTER(居中)、LVCFMT_RIGHT(右对齐)
nWidth 这1列的宽度
nSubItem 子项的索引与列(一般缺省默认即可,不用填)
(3)InsertItem() 插入一行
int InsertItem(const LVITEM* pItem);// 可以插入图片(但是失败了,图片没能显示,所以这里不介绍)
int InsertItem(int nItem, LPCTSTR lpszItem) // 只能插入文字
nItem 第几行
lpszItem 这一行第1列的文字
(4)SetItemText() 设置文字
BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText);
nItem 列表中的第几行
nSubItem 列表中的低级列
lpszText 要显示的文字数据
效果图:
到这里,最基本的操作就说完了。不过,这里面有一个小细节的地方。如果仔细看代码会发现,我把列表的第一列的宽度设置成了0,而SetItemText()的时候,第1列的数据也是没有插入。这是因为:列表控件的第一列好像是叫虚列,当大数据的时候好像能够利用这个加快速度什么的,具体我也不是很清楚。但就是因为这个原因,我们会发现,第一列无法设置里面的文本居中对齐!!!即使设置成居中,仍然是左对齐的效果(大家可以试试)。所以,为了能够居中的显示,我这里就放弃了第一列。不过,如果是要显示图片的,或者是有CheckBox的列表,一定要有这个虚列,不然图片和CheckBox就无法显示了。如果仅仅是简单的文字,倒是可以这样达到第一列居中的效果。
2.接着,再来说说列表控件中CheckBox的使用
同样的,和1基本一样,就是在设置扩展样式中多了一个LVS_EX_CHECKBOXES
// ListCtrl2
m_list2.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES);
m_list2.InsertColumn(0, _T("姓名"), LVCFMT_LEFT, 100);
m_list2.InsertColumn(1, _T("年龄"), LVCFMT_LEFT, 100);
m_list2.InsertColumn(2, _T("性别"), LVCFMT_LEFT, 100);
for(int i = 0;i <= 7;i++) {
strName.Format(_T("小石头%d"), i);
strAge.Format(_T("%d"), 20 + i);
strSex = i % 2 ? _T("男") : _T("女");
m_list2.InsertItem(i, _T(""));
m_list2.SetItemText(i, 0, strName);
m_list2.SetItemText(i, 1, strAge);
m_list2.SetItemText(i, 2, strSex);
}
那么怎么获取打了勾的行呢?这里我加了2个单选框:全选 和 反选给全选单选框添加单击事件
void CXXXDlg::OnBnClickedRadioAllSelect()
{
for(int i = 0;i < m_list2.GetItemCount();i++) {
m_list2.SetCheck(i, TRUE);
m_list2.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
}
}
给反选单选框添加单击事件
void CXXXDlg::OnBnClickedRadioInvertSelect()
{
BOOL state;
for(int i = 0;i < m_list2.GetItemCount();i++) {
state = m_list2.GetCheck(i);
if(state == FALSE) {
m_list2.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
m_list2.SetCheck(i, TRUE);
}
else {
m_list2.SetItemState(i, ~LVIS_SELECTED, LVIS_SELECTED);
m_list2.SetCheck(i, FALSE);
}
}
}
这里又牵涉到几个函数GetCheck()、SetCheck()、GetItemState()、SetItemState()。顾名思义,这几个函数的意思分别就是:获取和设置复选框的状态(打钩否)、获取和设置某一行的状态(选中否)。用法比较简单,看上面的例子就肯定知道了。
效果图:
3.最后,再介绍一下自绘ListCtrl
因为列表控件选中某一行的时候,高亮的颜色是蓝色,这点本人不是很喜欢。因为以前想做个类似QQ一样的好友列表的,一开始选的是用ListCtrl来显示(对好友不分类的情况下),但是选中某一行的颜色是蓝色太难看,所以也就放弃了。这次,决心要好好研究一下,所以在网上找了许多资料都是介绍怎么重绘的。后来在网上找到一个现成的CMyListCtrl的类,里面说是能设置奇行、偶行、热点行、选中的背景和文字的颜色。但是唯独选中行的颜色有点BUG,无法实现修改颜色。在多次尝试之后,终于发现BUG所在。修改过的代码:
void CListCtrlEx::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLVCUSTOMDRAW pNMCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
int itemIndex = pNMCD->nmcd.dwItemSpec;
if (pNMCD->nmcd.dwDrawStage == CDDS_PREPAINT) {
*pResult = CDRF_NOTIFYITEMDRAW;
}
else if (pNMCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
// 选中行(鼠标选中的行)
if(GetItemState(itemIndex,LVIS_SELECTED) == LVIS_SELECTED) {
pNMCD->nmcd.uItemState = ~CDIS_SELECTED;
pNMCD->clrTextBk = m_selectItemBkColor;
pNMCD->clrText = pNMCD->clrFace = m_selectItemTextColor;
}
// CheckBox打钩行
else if(GetCheck(itemIndex) && (GetExtendedStyle() & LVS_EX_CHECKBOXES)) {
pNMCD->clrTextBk = m_selectItemBkColor;
pNMCD->clrText = m_selectItemTextColor;
}
// 热点行(鼠标停在上方)
else if(itemIndex==m_hoverIndex) {
pNMCD->clrTextBk = m_hoverItemBkColor;
pNMCD->clrText = m_hoverItemTextColor;
}
// 偶数行(比如 0、2、4、6)
else if(itemIndex % 2==0){
pNMCD->clrTextBk=m_evenItemBkColor;
pNMCD->clrText=m_evenItemTextColor;
}
// 奇数行(比如 1、3、5、7)
else{
pNMCD->clrTextBk = m_oddItemBkColor;
pNMCD->clrText = m_oddItemTextColor;
}
*pResult = CDRF_NEWFONT;
}
}
在这里,我在这个基础上,写了一个CListCtrlEx类,修改和加入了其他的一些功能,可以支持:
(1)奇数行背景颜色(默认白色)
(2)偶数行背景颜色(默认白色)
(3)热点行背景颜色(默认白色)
(4)选中行背景颜色(默认蓝色)
(5)奇数行文本颜色(默认黑色)
(6)偶数行文本颜色(默认黑色)
(7)热点行文本颜色(默认黑色)
(8)选中行文本颜色(默认黑色)
(9)点击列表头,对列表内的数据进行升序/降序排列
(10)双缓冲,解决了闪烁的问题
传1张简单的效果图:
https://img-my.csdn.net/uploads/201405/03/1399120330_1102.gif
CListCtrlEx类下载地址:
--------------------- 本文来自 SmallStoneSK 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/smallstonesk/article/details/24931273?utm_source=copy
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。