这个控件其实不用阿拉来介绍,因为它太常见了,就好像我们一出门就会看到妹子一样常见。当然也可以说,它是对ListBox的扩充。
在使用该控件之前,我先介绍VS的一个相当好玩的功能。
在代码文件的#include指令上右击,从弹出的菜单中选择“生成包含文件关系图”,如下图:
![](https://box.kancloud.cn/2016-06-14_575fd2d318950.png)
然后你喝一口咖啡,你会看到这样的东西:
![](https://box.kancloud.cn/2016-06-14_575fd2d32fc5e.png)
这个关系图,演示了你的项目中的头文件,源文件以及外部引用文件之间的关系。把鼠标移到上面,滚动滑轮,可以缩放大小。把鼠标移到“外部”节点上,点击左边的向下箭头,可以看到本项目与外部头文件的关系。
![](https://box.kancloud.cn/2016-06-14_575fd2d3522aa.png)
![](https://box.kancloud.cn/2016-06-14_575fd2d362ddc.png)
所以,如果你的程序比较复杂,头文件众多,不妨试试这功能。
![](https://box.kancloud.cn/2016-06-14_575fd2d3a0634.png)
=====================================================
下面我们来使用ListView来显示一组数据,我定义了一个结构体:
~~~
// 用于测试的结构体
struct STUDENTINFO
{
WCHAR Name[15];
WCHAR Age[3];
WCHAR Address[50];
};
~~~
假设它代表了一位学员的信息——姓名、年龄、地址。
我们要用ListView来显示一些学员的信息,显然,每一个学员信息都有三个字段,ListView有多种视图,如图:
列表小图标
![](https://box.kancloud.cn/2016-06-14_575fd2d3d2332.png)
大图标
![](https://box.kancloud.cn/2016-06-14_575fd2d3e4e8b.png)
平铺
![](https://box.kancloud.cn/2016-06-14_575fd2d40e187.png)
详细视图
![](https://box.kancloud.cn/2016-06-14_575fd2d423a8f.png)
我们要显示多个字段,故应选择最后一种视图。
好,下面我们就做一个练习,实例是检验学习成果的唯一标准。
1、新建一个对话框资源,在设计器中拖一个List Control和两个Button,List Control其实就是ListView控件。
![](https://box.kancloud.cn/2016-06-14_575fd2d437e65.PNG)
设置View属性为Report。
![](https://box.kancloud.cn/2016-06-14_575fd31047772.PNG)
2、在对话框消息处理函数中,处理WM_INITDIALOG消息,向ListView添加列。
~~~
case WM_INITDIALOG:
// 获取ListView控件的句柄
hListview = GetDlgItem(hDlg, IDC_LV);
// 设置ListView的列
LVCOLUMN vcl;
vcl.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
// 第一列
vcl.pszText = L"姓名";//列标题
vcl.cx = 90;//列宽
vcl.iSubItem = 0;//子项索引,第一列无子项
ListView_InsertColumn(hListview, 0, &vcl);
// 第二列
vcl.pszText = L"年龄";
vcl.cx = 90;
vcl.iSubItem = 1;//子项索引
ListView_InsertColumn(hListview, 1, &vcl);
// 第三列
vcl.pszText = L"地址";
vcl.cx = 200;
vcl.iSubItem = 2;
ListView_InsertColumn(hListview, 2, &vcl);
return 0;
~~~
向LV添加列,调用ListView_InsertColumn宏,注意它是宏不是函数(你也可以发送LVM_INSERTCOLUMN消息),其中有一个参数是指向LVCOLUMN结构体的指针,关于这个结构体的成员我就不说了,有兴趣的看MSDN。
这样,LV控件就有了三个列了,就像这样。
![](https://box.kancloud.cn/2016-06-14_575fd3105bfa8.PNG)
3、另外两个按钮, 一个用来向LV中添加项,后一个是清除所有项。
还记得吧,要响应按钮单击,要处理WM_COMMAND消息,然后通过wParam参数的低字节位来判断用户点击了哪个按钮,指示了对应按钮的ID。
~~~
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BTNADD)
{
STUDENTINFO stu[ ] = {
{ L"小刘", L"20", L"火星" },
{ L"老赵", L"21", L"木星" },
{ L"小胡", L"30", L"水星" },
{ L"老高", L"32", L"山沟一号" },
{ L"黄牛", L"24", L"不知哪个星球来的" },
{ L"王七", L"28", L"超人之乡" }
};
//求出数组中元素的个数
int arrCount = (int)(sizeof(stu) / sizeof(stu[0]));
LVITEM vitem;
vitem.mask = LVIF_TEXT;
for (int i = 0; i < arrCount; i++)
{
/*
策略:
先添加项再设置子项内容
*/
vitem.pszText = stu[i].Name;
vitem.iItem = i;
vitem.iSubItem = 0;
ListView_InsertItem(hListview, &vitem);
// 设置子项
vitem.iSubItem = 1;
vitem.pszText = stu[i].Age;
ListView_SetItem( hListview, &vitem);
vitem.iSubItem = 2;
vitem.pszText = stu[i].Address;
ListView_SetItem(hListview, &vitem);
}
}
else if(LOWORD(wParam) == IDC_BTNCLEAR)
{
// 清除ListView中的所有项
ListView_DeleteAllItems(hListview);
}
return 0;
~~~
首先,为了在LV中加入数据,声明了一个STUDENT数组,STUDENT结构体在前面定义的,表示一位学员的信息。由于这个数组在声明的时候,并没有指定元素个数,在后面执行for循环添加项之前,先要知道数组中有多少个元素。
方法是用sizeof运算符取出整个数组的字节长度,然后除以第一个元素的长度,这样就求出元素的个数了。
向LV添加项,调用ListView_InsertItem宏,注意添加方法,要先添加项,随后再用ListView_SetItem宏来设置子项的内容。由于两个宏使用相同的参数,所以在循环前,我们都用一个LVITEM,在循环中我们只改变它的项索引值和文本内容再传到ListView_InsertItem宏或ListView_SetItem宏,这样也免得多次分配内存数据。
清除LV中的所有项,直接用ListView_DeleteAllItems宏就可以了。
以上操作也可以通过发送对应消息来完成,不过,直接调用宏似乎比SendMessage方便。
最后,看一下最终结果。
![](https://box.kancloud.cn/2016-06-14_575fd3106ddda.PNG)
由于这个例子相对有些复杂,稍后我把代码上传到[资源]中。
- 前言
- (1):关于C++的几个要点
- (2):完整的开发流程
- (3):窗口的重绘
- (4):创建菜单
- (5):具有单选标记的菜单
- (6):创建右键菜单
- (7):多边形窗口
- (8):绘图(A)
- (9):绘图(B)
- (10):绘图(C)
- (11):使用控件——先来耍一下按钮
- (12):使用控件——单选按钮
- (13):握手对话框
- (14):用对话框作为主窗口
- (15):ListView控件
- (16):ListView的多个视图
- (17):启动和结束进程
- (18):使用对话框的两个技巧
- (19):浏览和打开文件
- (20):浏览文件夹
- (21):复制&amp;粘贴&amp;剪贴板操作
- (22):抓取屏幕
- (23):渐变颜色填充
- (24):计时器
- (25):监视剪贴板