本帖最后由 ivccav 于 2023-3-25 13:49 编辑
之前写过3篇关于Listview控件的帖子(如下),阅读人数还挺多,其中一帖阅读量10W+,该控件受欢迎程度可见一斑。
随着64位Office开始支持Listview控件,我想需要了解该控件使用的需求只会更大。
VBA窗体Listview控件完全教程
https://club.excelhome.net/thread-1424969-1-1.html
用NM_CUSTOMDRAW自定义绘制技术实现Listview控件隔行换色
https://club.excelhome.net/thread-1428537-1-1.html
窗体Listview控件实现可编辑功能的完美解决方法
https://club.excelhome.net/thread-1423746-1-1.html
虽然曾经写过“完全教程”,但有一个问题始终没有解决,即Listview控件的网格线颜色无法设定。
我在微软官网查阅了很多NM_CUSTOMDRAW内容,找不到设置网格线颜色的内容。NM_CUSTOMDRAW用于设置每行交替色是很方便的,代码简单。
众所周知,控件绘制可有三种方式:
1.处理 WM_PAINT消息
这是最极端的方式,执行一个 WM_PAINT 处理程序,并且自己完成所有的绘制工作。这意味着代码将需要进行一些与呈现控件相关的琐事 — 创建适当的设备上下文(一个或多个),决定控件的大小和位置,绘制控件等。在绘制过程中,很少需要这种级别的控件。
2.所有者绘制(OwnerDraw)
控制控件绘制的第2种方法是所有者绘制,它是用于开发自定义控件最普通的技术。该技术普遍使用的主要原因在于,系统可为提供很多帮助。在呈现控件的之前,Windows已经创建并填写了设备上下文,决定了控件的大小和位置,并且向您传递信息以使您了解此刻绘制的需求。对于列表控件(例如Listbox和Listview等),Windows将为列表中的每一项调用绘制代码,这意味着您只需绘制这些项,而无需考虑控件的其他方面。这里的”Owner”可以理解为控件类的派生类。
如何启用控件的OwnerDraw属性呢?对于ListView控件,可以设置LVS_OWNERDRAWFIXED风格。
使用OwnerDraw方式,我们需要处理WM_MEASUREITEM和WM_DRAWITEM消息。
如果要设置每行行高,只能使用OwnerDraw方式绘制,且只有在收到WM_MEASUREITEM消息时能进行设置。
设置行高在MEASUREITEMSTRUCT结构体的ItemHeight成员中设置。
Private Type MEASUREITEMSTRUCT
CtlType As Long
CtlID As Long
itemID As Long
itemWidth As Long
ItemHeight As Long
itemData As Long
End Type
所有者绘制(OwnerDraw)方式主要处理WM_DRAWITEM消息对Item和Subitem进行边框绘制。
3.自定义绘制(CustomDraw)
CustomDraw不需要设置风格。只需在接收到NM_CUSTOMDRAW通知时(借由WM_NOTIFY消息)给父窗口。控件的父窗口可以选择处理或不处理此通知。在CustomDraw场景下,控件的大部分绘制工作还是由系统默认完成,我们只是在系统绘制之前或者之后对控件的呈现进行某种方式的”微调”。比如,我们可以使用CustomDraw机制来修改ListView控件中的项目背景色,文字的前景或背景色等。在控件绘制的整个阶段中,系统划分了一系列不同的阶段,开发者设置了感兴趣的阶段后,系统就会在每个开发者感兴趣的阶段发送NM_CUSTOMDRAW通知。当我们收到NM_CUSTOMDRAW通知的时候,我们可以根据通知中的DrawStage知道当前绘制的阶段。具体可看微软官方文档。
本帖使用的是第二种方式。代码来源于网络,是VB6环境下写的一个类模块。如果直接放在VBA中运行,会导致应用软件直接崩溃。我修改了少量参数,让其可以在VBA中正常运行,并针对在VBA中无法触发WM_MEASUREITEM消息导致无法设置行高的问题,写了触发该消息的子过程。还写了应用示例。
该类的接口如下:
应用实际效果图:
附件下载见10楼:
64位API声明参考:
https://club.excelhome.net/thread-1656964-1-1.html