[Win32SDK基本]ListView Controls(1)Report (details) View 详解

来源:互联网 发布:淘宝突然没有访客了 编辑:程序博客网 时间:2024/06/06 01:20
本文由CSDN用户zuishikonghuan所作,转载请注明出处:http://blog.csdn.net/zuishikonghuan/article/details/46877001

老规矩,先上MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/bb774737(v=vs.85).aspx

其实还是子窗口,static那节说的很明白了,就不重复了 ,这个控件的类名是SysListView32

还是以我的博客“窗口详解”(地址:http://blog.csdn.net/zuishikonghuan/article/details/46378475)中的代码为基础,继续编写

需要包含CommCtrl.h头文件和链接comctl32.lib

listview是非常实用的控件,先看几张来自MSDN的图,饱饱眼福:

分类:listview分好几类,今天说说Report (details) View报表列表控件

报表列表控件的风格是:LVS_REPORT

一。listview常用风格(其实很多,这里只说最常用的,其他的看MSDN)

1。LVS_SINGLESEL
只能同时选择一项。默认情况下,可以选择多个项。

2。LVS_NOSORTHEADER
列标题按钮不工作。即如果单击在报表头中的列标题不进行操作。

3。LVS_SHOWSELALWAYS
如果有的话,总是显示所选内容,即使该控件没有焦点。

二。listview常用扩展风格(其实很多,这里只说最常用的,其他的看MSDN)

1。LVS_EX_FULLROWSELECT
当选定一项,则该项目及其所有子项全部突出显示(就是说选中时高亮一行)。这种风格是仅在 LVS_REPORT 样式中可用。

2。LVS_EX_SUBITEMIMAGES
允许子项显示图像。这种风格是仅在 LVS_REPORT 样式中可用。

3。LVS_EX_GRIDLINES
显示网格线。这种风格是仅在 LVS_REPORT 样式中可用。

使用扩展风格,必须用LVM_SETEXTENDEDLISTVIEWSTYLE 消息添加扩展风格,直接在CreateWindowEx里面添加是无效的。
或者用ListView_SetExtendedListViewStyle函数
参数1:句柄
参数2:扩展风格

三。控制消息:

1。LVM_INSERTCOLUMN 插入新列
wParam:新列的索引
lParam:指向包含新列的属性的 LVCOLUMN 结构的指针。
返回值:成功返回新列的索引,失败返回-1

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 #if (_WIN32_WINNT >= 0x0600)  int    cxMin;  int    cxDefault;  int    cxIdeal;#endif } LVCOLUMN, *LPLVCOLUMN;

mask:
LVCF_FMT:Fmt 成员是有效的。
LVCF_WIDTH:Cx 成员是有效的。
LVCF_TEXT:PszText 成员是有效的。
LVCF_SUBITEM:ISubItem 成员是有效的。
LVCF_IMAGE:4.70 版本。iImage成员是有效的。
LVCF_ORDER:4.70 版本。iOrder的成员是有效的。
LVCF_MINWIDTH:版本 6.00 和 Windows Vista.The cxMin 成员是有效。
LVCF_DEFAULTWIDTH:版本 6.00 和 Windows Vista.The cxDefault 成员是有效。
LVCF_IDEALWIDTH:版本 6.00 和 Windows Vista.The cxIdeal 成员是有效。

fmt:列标题和列中的子项文本的对齐方式。
此成员可以是下列值的组合。请注意,并非所有组合都都有效。
LVCFMT_LEFT:文本是左对齐的。
LVCFMT_RIGHT:文本为右对齐。
LVCFMT_CENTER:文本居中。
LVCFMT_JUSTIFYMASK:用于选择控制领域的理由的那些 fmt 的位掩码。若要检查某一列的格式,请使用逻辑","LCFMT_JUSTIFYMASK 结合裂变材料条约。然后可以使用 switch 语句来确定是否已设置 LVCFMT_LEFT,LVCFMT_RIGHT 或 LVCFMT_CENTER 位。
LVCFMT_IMAGE:4.70 版本。该项显示的图像列表中的图像。
LVCFMT_BITMAP_ON_RIGHT:4.70 版本。该位图显示在右侧的文本。这并不影响图像列表中的图像分配到的标头项。
LVCFMT_COL_HAS_IMAGES:4.70 版本。标头项包含图像列表中的图像。
LVCFMT_FIXED_WIDTH:版本 6.00 和 Windows Vista。不能调整大小的列;就像 HDF_FIXEDWIDTH 一样。
LVCFMT_NO_DPI_SCALE:版本 6.00 和 Windows Vista。如果不设置,CCM_DPISCALE 将治理加大固定宽度。
LVCFMT_FIXED_RATIO:版本 6.00 和 Windows Vista。与行的高度,宽度会增加。
LVCFMT_SPLITBUTTON:版本 6.00 和 Windows Vista。列是一个拆分按钮 (与 HDF_SPLITBUTTON 相同)。列的标题显示拆分按钮 (与 HDF_SPLITBUTTON 相同)。

cx:列的宽度,以像素为单位。

pszText:如果设置的列信息,则此成员是字符串的一个 null 终止的字符串指针。如果结构接收有关列的信息,该成员指定的接收列标头文本的缓冲区的地址。

cchTextMax:在 TCHARs 的 pszText 成员所指向的缓冲区的大小。如果结构不接收有关列的信息,此成员将被忽略。
iSubItem:与该列关联的子项的索引。iImage:4.70 版本。图像在图像列表内的从零开始的索引。指定的图像将出现在列。
iOrder:4.70 版本。零开始的列偏移量。列偏移是左到右的顺序。例如,0 表示最左边的列。cxMin:Windows Vista。以像素为单位的列的最小宽度。
cxDefault:Windows Vista。应用程序定义的值,通常用来存储列的默认宽度。通过该列表视图控件,此成员将被忽略。
cxIdeal:Windows Vista。只读。以像素为单位,作为列的列的理想宽度目前可能指示到较小的宽度。

2。LVM_INSERTITEM 在列表视图控件中插入一个新的项目
wParam:必须为0
lParam:指针,指向 LVITEM 结构,它指定列表视图项的属性。使用代理权成员指定的从零开始的索引,应在其中插入新的项目。如果此值大于 listview 中当前包含的项数,新项目将追加到列表的末尾,并分配正确的索引。检查消息的返回值来确定分配给物料的实际索引。
返回值:成功返回新项目的索引,失败返回-1

LVITEM 结构:

typedef struct {  UINT   mask;  int    iItem;  int    iSubItem;  UINT   state;  UINT   stateMask;  LPTSTR pszText;  int    cchTextMax;  int    iImage;  LPARAM lParam;#if (_WIN32_IE >= 0x0300)  int    iIndent;#endif #if (_WIN32_WINNT >= 0x0501)  int    iGroupId;  UINT   cColumns;  PUINT  puColumns;#endif #if (_WIN32_WINNT >= 0x0600)  int    *piColFmt;  int    iGroup;#endif } LVITEM, *LPLVITEM;

mask:
LVIF_COLFMT:Windows Vista 及更高版本。PiColFmt 成员是有效的或者必须设置。如果使用此标志,则分栏成员是有效的或必须设置。
LVIF_COLUMNS:分栏成员是有效的或者必须设置。
LVIF_DI_SETITEM:操作系统应该存储请求的列表项目信息并没有再问了。此标志仅用于 LVN_GETDISPINFO 通知代码。
LVIF_GROUPID:IGroupId 成员是有效的或者必须设置。如果未设置此标志,当发送 LVM_INSERTITEM 消息,iGroupId 的值被假定为 I_GROUPIDCALLBACK。
LVIF_IMAGE:iImage成员是有效的或者必须设置。
LVIF_INDENT:IIndent 成员是有效的或者必须设置。
LVIF_NORECOMPUTE:该控件将不生成 LVN_GETDISPINFO 来检索文本信息,如果它收到一条 LVM_GETITEM 消息。相反,pszText 成员将包含 LPSTR_TEXTCALLBACK。
LVIF_PARAM:LParam 成员是有效的或者必须设置。
LVIF_STATE:state成员是有效的或必须设置。
LVIF_TEXT:PszText 成员是有效的或者必须设置。

iItem:此结构引用的项的从零开始的索引。

iSubItem:一开始的索引,这种结构所指,该子项或零如果这种结构是指一个项目,而不是一个子项。

state:指示项的状态、 状态图像和覆盖图像。StateMask 成员指示此成员的有效位。位 0 到 7 的此成员包含项目状态标志。这可以是一个或多个项目状态的值。通过此成员 11 8 位指定一个基于叠加图像索引。全尺寸的图标图像列表和小图标图像列表可以有覆盖图像。覆盖图像叠加到此项的图标图像。如果这些位均为零,该项目已经没有覆盖图像。若要隔离这些位,请使用 LVIS_OVERLAYMASK 掩码。若要在此成员设置覆盖图像索引,您应该使用 INDEXTOOVERLAYMASK 宏。用 ImageList_SetOverlayImage 函数设置图像列表覆盖图像。
通过此成员 15 12 位指定状态图像索引。状态图像显示在项目的图标来指示应用程序定义的状态旁边。如果这些位均为零,该项目已经没有国家形象。若要隔离这些位,请使用 LVIS_STATEIMAGEMASK 掩码。若要设置状态图像索引,请使用 INDEXTOSTATEIMAGEMASK 宏。状态图像索引应绘制状态图像列表中指定的图像的索引。与 LVM_SETIMAGELIST 消息指定状态图像列表。

stateMask:该值指定哪些位国家成员将检索或修改。例如,将此成员设置为 LVIS_SELECTED 将导致只状态的项目的选择要检索。
此成员允许您修改一个或多个项状态而无需首先检索所有项的状态。例如,将此成员设置为 LVIS_SELECTED 和状态为零将导致项目的选择状态被清除,但没有一个其他国家会受影响。
若要检索或修改的所有国家,请设置此成员到 (UINT)-1。
您可以使用宏 ListView_SetItemState 来设置,清除位。

pszText:如果结构指定项目属性,pszText 是一个指向以 null 结尾的字符串的指针。当响应 LVN_GETDISPINFO 通知,是确保此指针保持有效直到后下通知已收到。
如果结构接收物料属性,pszText 是指向接收项目的文本缓冲区的指针。请注意,虽然该列表视图控件允许任何长度字符串存储为项目文本,只有首先 260 TCHARs 显示。

如果 pszText 的值为 LPSTR_TEXTCALLBACK,该项目是一个回调项。如果回调文本发生更改,您必须显式将 pszText 设置为 LPSTR_TEXTCALLBACK 并通过发送 LVM_SETITEM 或 LVM_SETITEMTEXT 的消息通知列表视图控件的更改。
不要设置 pszText LPSTR_TEXTCALLBACK 如果列表视图控件具有的 LVS_SORTASCENDING 或 LVS_SORTDESCENDING 的风格。

cchTextMax:TCHARs 中 pszText,包括终止 NULL 所指向的缓冲区数。
当结构接收项目属性时,只使用此成员。当结构指定项目属性时,它将被忽略。例如,cchTextMax 在 LVM_SETITEM 和 LVM_INSERTITEM 的过程中将被忽略。它在只读 LVN_GETDISPINFO 和其他 LVN_ 通知。永远不会注意复制超过 cchTextMax TCHARs — — 凡 cchTextMax 包括终止 NULL — — 成 pszText LVN_ 通知期间,否则您的程序可能会失败。

iImage:该项目的图标控件的图像列表中的索引。这适用于大型和小型的图像列表中。如果此成员是 I_IMAGECALLBACK 值,父窗口是负责存储索引。在这种情况下,列表视图控件发送父 LVN_GETDISPINFO 通知代码,需要时,它显示的图像检索的索引。

lParam:特定于项目的价值。如果你使用 LVM_SORTITEMS 消息,列表视图控件将此值传递到应用程序定义的比较函数。您还可以使用 LVM_FINDITEM 消息来搜索具有指定需要 lParam 的值的项的列表视图控件。

iIndent:4.70 版本。以图像宽度计算,要缩进的项目数。一个单一的压痕等于项目图像的宽度。因此,值 1 通过一个图像,由两个图像,等等值 2 缩进的宽度缩进的项目。请注意,此字段仅为项目支持。尝试设置子项缩进会导致调用函数失败。

iGroupId:版本 6.0 标识符的组,该项目属于,或为下列值之一。
I_GROUPIDCALLBACK:Listview 控件发送父 LVN_GETDISPINFO 通知代码以检索组的索引。
I_GROUPIDNONE:该项目不属于组。

cColumns:版本 6.0 的数据列 (子项) 为此项平铺视图中显示的数目。最大值为 20。如果此值为 I_COLUMNSCALLBACK,列阵列和阵列本身 (puColumns) 的大小被通过发送一个 LVN_GETDISPINFO 通知。

puColumns:版本 6.0 为这一项目和这些列的顺序显示指定的列的列索引数组的指针。

piColFmt:Windows Vista: 不执行。Windows 7 和以后: 指向数组的以下标志 (单独或组合),指定在每个子项的格式扩展平铺视图。
LVCFMT_LINE_BREAK:部队要换到顶部的下一列的列表中的列。
LVCFMT_FILL:填充图块区域的其余部分。可能有一个标题。
LVCFMT_WRAP:允许在其列表中的列的剩余空间内换行的列。
LVCFMT_NO_TITLE:从子项中删除标题。
LVCFMT_TILE_PLACEMENTMASK:相当于 LVCFMT_LINE_BREAK 和 LVCFMT_FILL 的组合。

iGroup:Windows Vista: 组的项的索引。仅对所有者数据/回调 (多个组中的单个项) 有效。

3.LVM_SETITEM 设置设置子项的文本。
wParam:必须为0
lParam:指向包含新的项目属性的 LVITEM 结构的指针。如果掩码成员指定的 LVIF_TEXT 值,pszText 成员是以 null 结尾的字符串的地址,cchTextMax 成员将被忽略。
返回值:成功TRUE,失败FALSE

4。LVM_DELETEITEM 移除一项
wParam:要删除项的序号
lParam:必须为0
返回值:成功TRUE,失败FALSE

5。LVM_DELETECOLUMN 移除列
wParam:要删除列的序号
lParam:必须为0
返回值:成功TRUE,失败FALSE

6。LVM_GETITEMCOUNT 获取项目数
wParam:必须为0
lParam:必须为0
返回值:返回项目的数量

7。LVM_GETITEM 获取指定项
wParam:必须为0
lParam:指向 LVITEM 结构的指针
返回值:成功返回TRUE,失败返回FALSE

注:关于获取指定项文本:
在 LVITEM 结构中的掩码成员设置 LVIF_TEXT 标志,iItem和iSubItem指定项目序号和子项。pszText 成员必须指向一个有效的缓冲区;cchTextMax 成员必须设置为该缓冲区中的字符数。应用程序不应假设文本一定将放置在指定的缓冲区。结果是可能改变结构中的 pszText 成员,以指向新的文本,而不是将它放在缓冲区中。

8。LVM_GETCOLUMN 获取指定列
wParam:列的序号
lParam:指向 LVCOLUMN 结构的指针
返回值:成功返回TRUE,失败返回FALSE

9。LVM_GETHOTITEM 获取当前选中项
wParam:必须为0
lParam:必须为0
返回值:返回选中项的序号

10。颜色:
文字颜色:获取:LVM_GETTEXTCOLOR 设置:LVM_SETTEXTCOLOR 
文字背景色:获取:LVM_GETTEXTBKCOLOR 设置:LVM_SETTEXTBKCOLOR 
背景色:获取:LVM_GETBKCOLOR 设置:LVM_SETBKCOLOR 
获取颜色的三个消息 wParam和 lParam 都必须为0,返回值都是颜色
设置颜色的三个消息 wParam 都必须为0,为颜色(RGB颜色),其中设置背景颜色的那两个消息颜色可以为 CLR_NONE,表示没有颜色。

四。通知消息:

1。NM_CLICK 项目被单击
通过 WM_NOTIFY 发送给父窗口
wParam:控件标识符
lParam:指向 NMHDR 结构的指针,从4.71版本开始,是指向NMITEMACTIVATE 结构的指针
返回值:不使用

typedef struct tagNMITEMACTIVATE {  NMHDR  hdr;  int    iItem;  int    iSubItem;  UINT   uNewState;  UINT   uOldState;  UINT   uChanged;  POINT  ptAction;  LPARAM lParam;  UINT   uKeyFlags;} NMITEMACTIVATE, *LPNMITEMACTIVATE;

hdr:指向 NMHDR 结构的指针
iItem:项目的序号,如果没有使用则为-1

typedef struct tagNMHDR {  HWND     hwndFrom;  UINT_PTR idFrom;  UINT     code;} NMHDR;
hwndFrom:控件句柄
idFrom:控件id
code:通知码

2。NM_DBLCLK 项目被双击
同上

3。NM_RCLICK 项目被右击
wParam和 lParam同上
返回值:非0表示不允许默认处理,0表示允许.

五。图片列表:
ImageList_Create 创建一个图片列表

HIMAGELIST ImageList_Create(
   int  cx,
   int  cy,
   UINT flags,
   int  cInitial,
   int  cGrow
);
cx:宽度
cy:高度
flags:置ILC_MASK
cInitial:图像列表最初包含的映像数目。
cGrow:图像的图像列表可以增长时,系统需要腾出新的图像数。此参数表示新的图像调整大小后的图像列表可以包含的数。

ImageList_Add添加位图
ImageList_AddIcon添加图标

ListView_SetImageList为listview设置图片列表

代码:
全局变量
HWND listview1;LVCOLUMN list1;LVITEM item1;HIMAGELIST imglist1;
代码:
LRESULT CALLBACK WndProc2(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){switch (uMsg){case WM_CREATE://创建listviewlistview1 = CreateWindowEx(WS_EX_STATICEDGE, TEXT("SysListView32"), NULL, WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL, 10, 10, 400, 400, hwnd, (HMENU)1, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);ListView_SetExtendedListViewStyle(listview1, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES);//设置listview扩展风格SendMessage(listview1, WM_SETFONT, (WPARAM)GetStockObject(17), 0);//SetWindowTheme(listview1, L"Explorer", NULL);//创建图片列表imglist1 = ImageList_Create(20, 20, ILC_MASK, 1, 1);ImageList_AddIcon(imglist1, LoadIcon((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), TEXT("ICON_2")));ImageList_AddIcon(imglist1, LoadIcon((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), TEXT("ICON_1")));ListView_SetImageList(listview1, imglist1, LVSIL_SMALL);//内存清零RtlZeroMemory(&list1, sizeof(LVCOLUMN));RtlZeroMemory(&item1, sizeof(LVITEM));//创建列list1.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;//掩码list1.fmt = LVCFMT_LEFT;//左对齐list1.cx = 100;//列宽list1.pszText = TEXT("醉时空欢");SendMessage(listview1, LVM_INSERTCOLUMN, 0, (LPARAM)&list1);//创建列list1.pszText = TEXT("Win32");list1.cx = 200;SendMessage(listview1, LVM_INSERTCOLUMN, 1, (LPARAM)&list1);list1.pszText = TEXT("MSDN");SendMessage(listview1, LVM_INSERTCOLUMN, 2, (LPARAM)&list1);list1.pszText = TEXT("happy");SendMessage(listview1, LVM_INSERTCOLUMN, 3, (LPARAM)&list1);//创建项目item1.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_INDENT;item1.pszText = TEXT("项目");item1.iItem = 0;//项目号item1.iImage = 0;//图片号item1.iIndent = 0;SendMessage(listview1, LVM_INSERTITEM, 0, (LPARAM)&item1);item1.iItem = 1;item1.iImage = 0;SendMessage(listview1, LVM_INSERTITEM, 0, (LPARAM)&item1);item1.pszText = TEXT("3");item1.iItem = 2;item1.iImage = 1;item1.iIndent = 1;//缩进一个图像单位SendMessage(listview1, LVM_INSERTITEM, 0, (LPARAM)&item1);//创建子项item1.mask = LVIF_TEXT | LVIF_IMAGE;item1.iItem = 1;item1.iSubItem = 1;item1.iImage = -1;item1.pszText = TEXT("子项");SendMessage(listview1, LVM_SETITEM, 0, (LPARAM)&item1);item1.iItem = 1;item1.iSubItem = 2;item1.pszText = TEXT("子项");SendMessage(listview1, LVM_SETITEM, 0, (LPARAM)&item1);item1.iItem = 1;item1.iSubItem = 3;item1.pszText = TEXT("子项");SendMessage(listview1, LVM_SETITEM, 0, (LPARAM)&item1);break;case WM_NOTIFY:switch (wParam){case 1://ID为listview的IDLPNMITEMACTIVATE now;now = (LPNMITEMACTIVATE)lParam;//得到NMITEMACTIVATE结构指针char a[50];_itoa(now->iItem, a, 10);//now->iItem项目序号switch (now->hdr.code){//判断通知码case NM_CLICK://MessageBoxA(hwnd, a, "单击", 0);break;case NM_DBLCLK://MessageBoxA(hwnd, a, "双击", 0);break;case NM_RCLICK://MessageBoxA(hwnd, a, "右击", 0);break;}break;}break;case WM_DESTROY:ImageList_Destroy(imglist1);//销毁图片列表PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, uMsg, wParam, lParam);}

效果图:

选中一项时:

将上面代码中的SetWindowTheme(listview1, L"Explorer", NULL);取消注释之后再运行:

有个虚线碍眼,挺难看的,其实这个问题困扰了我好长时间,MSDN和百度上也没有找到解决方法,用ControlSpy和Spy++倒腾了半天也没有结果,但经过我的不懈努力,终于研究出来了两个方法:

方法1.使用对话框,在对话框里创建的listview就没有虚线框

方法2.在NM_CLICK通知里面使listview失去焦点,在NM_CLICK里面加入:

SendMessage(now->hdr.hwndFrom, WM_KILLFOCUS, 0, 0);

不过这种方法可能会有一些隐患,目前尚不明确,不能加上LVS_SHOWSELALWAYS风格。

效果:







0 0
原创粉丝点击