news 2025/12/28 6:52:59

汇编语言全接触-31.列表视图控件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
汇编语言全接触-31.列表视图控件

本课中我们将学习如何创建和使用列表视图控件。

理论:

列表视图控件和树型视图、丰富文本编辑控件一样是通用控件的一种。可能您都已经知道了列表视图控件,只不过是不知道它的确切名字而已。列表视图控件可以用来很好地显示项目。在这方面它和列表框相同,只不过它的性能更强。

有两种方法创建一个列表视图控件。第一种也是最简单的方法是:用资源编辑器来创建它。用该种方法只是不要忘记在您的代码(的任何位置处)加入对InitCommonControls函数的调用(记得吗,调用该函数只是为了隐式地加载包含通用控件的DLL)。另一种方法是调用CreateWindowEx函数,这里您必须指定合适的类名,譬如:SysListView32,WC_LISTVIEW不是正确的类名

在列表视图种有四种方法来显示数据:大图标,小图标,列表和报告方式。这些方法和在资源管理器种选择View->Large Icons,Small Icons , List 和 Details 相对应。各种不同的显示方式只是显示了不同的外观而已。譬如,您可能有许多的数据,只是并不想全部显示。报告方式提供的消息最完全,其它的方式则要少得多。在刚创建一个列表视图时您可以选择一种初始显示方法,随后您可以调用SetWinodwLong函数并设置GWL_STYLE标志位来改变显示方式

既然我们已经知道了如何创建列表控件,接下来我们学习如何使用它们。我们将主要集中在报告方式的显示上,因为该种方式演示了最多的列表控制的特性。使用列表控制的步骤如下:

调用CreateWindowEx函数来创建一个列表控件,指定它的类名为SysListView32。您还可以在此处指定控件初次显示时的方式。

创建和初始化用在列表控件中显示项目的图象列表(如果存在)。

向列表控件中插入列,如果显示的方式是报告方式这一步是必须的。

向控件中插入项目和自项目。

列:

在报告方式中,有不止一个列。您可以把放入到列表控件中的数据看作是一张表单:这时数据是按行列排列的。在控件中至少有一列。在其它的显示方式中则无所谓,因为这些显示方式有仅有一列。

加入列要通过向列表控件发送LVM_INSERTCOLUMN消息来实现。

LVM_INSERTCOLUMN

wParam = iCol

lParam =指向LV_COLUMN型结构体变量的指针

iCol 列数,从0开始编号。

LV_COLUMN 包含了将插入的列的信息。它的定义如下:

LV_COLUMN STRUCT

imask dd ?

fmt dd ?

lx dd ?

pszText dd ?

cchTextMax dd ?

iSubItem dd ?

iImage dd ?

iOrder dd ?

LV_COLUMN ENDS

Field name

Meanings

imask

一组标志位,它指示了该结构体中的那些成员变量是有效的。该结构体中的成员变量并不是同时有效的。在某些时候,可能只有某些成员变量是有效的。结构体可以用来输入和输出。这样让WINDOWS知道那些成员变量是有效的是非常重要的。可能的标志有:

LVCF_FMT = fmt有效

LVCF_SUBITEM = iSubItem有效

LVCF_TEXT = pszText有效.

LVCF_WIDTH = lx有效

您可以一次使用几个标志。譬如,如果您向指定列的文本标签(列名),您必须在pszText成员变量中提供列名,然后指定标志LVCF_TEXT告诉WINDOWS成员变量pszText中的值是有效的,否则WINDOWS将忽略掉pszText中的值。

fmt

指定了项目/子项目的对齐方式。可能的值有:

LVCFMT_CENTER = 文本居中

LVCFMT_LEFT = 文本左对齐

LVCFMT_RIGHT = 文本右对齐

lx

lx 是列的宽度(以像素点为单位)。以后您可以发送消息LVM_SETCOLUMNWIDTH来改变列的宽度。

pszText

如果用来设定列的属性时,该成员变量为指向列名的指针。如果是查询列名,该成员变量指向一个足够大的缓冲区,用来接收返回的列名,这是您必须在成员cchTextMax中指定缓冲区的大小。如果是设定列名时,可以忽略该变量,因为该指针指向的是一个ASCII码的字符串,而WINDOWS可以解析出ASCII串的长度。

cchTextMax

cchTextMax 以字节计的上面一个成员变量指向的缓冲区的小。该成员变量只在您查询列的属性时使用。如果是设定列的属性,那该变量将被忽略。

iSubItem

指定和该列相连的子项目的索引号。该成员变量的值用来标识和列相连系的子项目。该列的使用最好地说明了如何把列号和子项目相连。要查询列的属性时可以发送LVM_GETCOLUMN消息,并在成员变量imask中指定LVCF_SUBITEM标志,列表控件将在iSubItem中返回插入时设定的iSubItem值。为了使用该办法,您需要在该成员变量中放入正确的值。

iImage and iOrder

为了和IE3.0以上版本兼容。目前我没有这方面的资料。

在列表视图控件创建后,您必须至少向其中插入一列。当然如果不打算使用报告方式显示,那倒是没有必要插入列。为了插入列,您需要定义一个LV_COLUMN型的结构体变量,给其成员变量赋上正确的值,指定列号,然后向列表视图控件发送LVM_INSERTCOLUMN消息并把该结构体变量的值传过去。

LOCAL lvc:LV_COLUMN

mov lvc.imask,LVCF_TEXT+LVCF_WIDTH

mov lvc.pszText,offset Heading1

mov lvc.lx,150

invoke SendMessage,hList, LVM_INSERTCOLUMN,0,addr lvc

上面的代码段显示了该过程。当发送LVM_INSERTCOLUMN消息时,他指定了列的标题条文本和它的宽度。

项目和子项目

项目是列表视图中主要的内容。除报告方式显示的外,在列表视图您只能看到项目。子项目是项目的详细信息。一个项目可能有不止一个相关的子项目。举个例子,譬如项目是文件名,那其相关的子项目可能有文件属性、大小、创建日期等。在报告方式的视图中,最左边一列是项目,其它列是子项目。从数据库记录的角度看,项目类似主键,子项目类似记录。

至少您的列表视图需要一些项目:子项目是可选的。如果您想要给用户提供更多的信息,可以把子项目和项目相连,然后放到列表视图中以报告的方式显示。

您可以通过向列表视图发送LVM_INSERTITEM消息来向其中添加项目,这时还需要把一个指向LV_ITEM型的结构体的变量的指针放到lParam一同传给列表视图。LV_ITEM的定义如下:

LV_ITEM STRUCT

imask dd ?

iItem dd ?

iSubItem dd ?

state dd ?

stateMask dd ?

pszText dd ?

cchTextMax dd ?

iImage dd ?

lParam dd ?

iIndent dd ?

LV_ITEM ENDS

Field name

Meanings

imask

一组标志位标明该结构体中那些成员变量中的值有效。它的意义和上面我们提到的LV_COLUMN型结构体中向对应的成员变量基本相同。更详细的信息,可以查询WIN32 API 手册。

iItem

该结构体代表的项目的索引号。索引号是从0开始编号的。该值和表单的“行”类似。

iSubItem

和上一个成员变量指定的项目相连的子项目的索引号。您可以把它当作表单的“列”。譬如您想要把一个项目插入到新创建的列表视图控件,iItem的值应为0(因为该项目是第一个项目),iSubItem的值也应当为0(我们想把该项目插到第一列)。如果你想指定一个子项目和该项目相连,iItem中应该是您想要相连的项目的索引号,iSubItem的值应当是大于0的值,具体的值取决于您想把该子项目插在那一列。如果你的列表视图控件一共有4列的化,第一列包含了项目,其余3列是留给子项目的。如果您想把子项目插在第四列,应当指定该值为3。

state

该成员变量包含的标志位反应了项目的状态。状态的改变可能是由用户的操作引起的或是程序改变的。这些状态包括:是否有焦点/高亮度显示/被选中(由于被剪切)/被选中等。另外还包括,以1为基数的索引用来代表是否处使用重叠/状态图标。

stateMask

由于上面的成员变量包含状态标志位、重叠的位图索引号、和状态位图的索引号,我们需要告诉WINDOWS我们到底需要设定或查询那一个值。该成员变量就是用来做这项工作的。

pszText

当我们想设定项目的属性时,它包含项目名称的ASCII码的字符串的地址。当查询项目的属性时,该成员变量将用来接收查询返回的项目的名称。

cchTextMax

仅当您用来查询项目的属性时才需要使用该值,这时它包含上一个成员变量的大小。

iImage

图标在列表视图中的图象链表中的索引号。

lParam

用户定义的值,当您给项目排序时使用。当您告诉列表视图对项目排序时,列表视图将成对地比较项目。 它将会把两个项目的lParam的值传给您,这样您就可以进行比较先列出那一个了。如果您现在还不太明白的话,没有系,我们稍后还要讲关于排序的问题。

现在让我们来总结想列表控件中插入项目/子项目的步骤:

定义一个LV_ITEM型的结构体变量。

给该变量赋给合适的值

如果要插入一个项目,就向列表视图控件发送LVM_INSERTITEM值。 如果要插入一个子项目,发送LVM_SETITEM。如果您不明白项目和子项目之间的关系的话,可能会有一些疑惑。子项目仅是项目的属性而已,也就是说您可以插入一个项目但是不能插入一个子项目。所以添加一个子项目十只能发送LVM_SETITEM消息而不能发送LVM_INSERTITEM消息。

列表视图控件的消息/通知

既然您知道了如何创建和往其中添加内容,下一步就是如何和它通讯。列表视图控件和它的父窗口之间的通讯是通过消息/通知来进行的。父窗口通过发送消息来控制列表视图控件,列表视图控件通过发送WM_NOTIFY消息来通知它的父窗口。这一点和其它的通用控件没有什么不同。

排序项目/子项目

您可以在调用CreateWindowEx函数时指定LVS_SORTASCENDING 或 LVS_SORTDESCENDING风格来指定缺省的排序方式。这两种风格仅仅排序项目的名称。如果想要排序项目的其它属性,您可以通过发送LVM_SORTITEMS消息来完成

LVM_SORTITEMS

wParam = lParamSort

lParam = pCompareFunction

lParamSort 用户定义的值,该值将传递给用来比较的函数。

pCompareFunction 用户定义的用来比较排序的函数的地址。该函数的原型如下:

CompareFunc proto lParam1:DWORD, lParam2:DWORD, lParamSort:DWORD

lParam1 和 lParam2 是 LV_ITEM型的结构体中的成员变量lParam的值。

lParamSort 是发送LVM_SORTITEMS消息时参数wParam中的值

当列表视图控件接收到LVM_SORTITEMS消息时,当需要比较项目时它会调用在lParam中指定的比较函数。比较函数将决定那一个项目排在前面。方法很简单:如果函数返回一个负值,由(lParam代表的)第一个项目排在前,如果返回正值,第二个项目排在前。如果相等,必须返回0 。

真正使得该方法能够运行的是LV_ITEM型结构体中的成员变量lParam值。当您需要排序时(譬如当您点击列的标题条时),您需要考虑好排序方案。在本例中,我们把项目的索引放到该成员变量中,这样我们可以通过发送LVM_GETITEM消息来得到项目的其它信息。注意:当项目重排序后,它们的索引也就变了。所以当重排序后,我需要在lParam参数中反应出新的索引。如果您想在用户点击列的标题条时重新排序,您需要在您的窗口过程函数中处理LVN_COLUMNCLICK通知消息。LVN_COLUMNCLICK消息是随同WM_NOTIFY消息一起发送的。

例子:

该例子创建了一个列表视图控件,并在其中显示了当前文件夹中的文件大小和文件名。缺省的视图是报告方式的,如果您点击列标题条,标题将按升/降序重新排列。您可以通过菜单选择不同的显示方式(大图标、小图标等)。当您双击一个项目时,项目的名称将显示在一个对话框中。

.386

.model flat,stdcall

option casemap:none

include \masm32\include\windows.inc

include \masm32\include\user32.inc

include \masm32\include\kernel32.inc

include \masm32\include\comctl32.inc

includelib \masm32\lib\comctl32.lib

includelib \masm32\lib\user32.lib

includelib \masm32\lib\kernel32.lib

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

IDM_MAINMENU equ 10000

IDM_ICON equ LVS_ICON

IDM_SMALLICON equ LVS_SMALLICON

IDM_LIST equ LVS_LIST

IDM_REPORT equ LVS_REPORT

RGB macro red,green,blue

xor eax,eax

mov ah,blue

shl eax,8

mov ah,green

mov al,red

endm

.data

ClassName db "ListViewWinClass",0

AppName db "Testing a ListView Control",0

ListViewClassName db "SysListView32",0

Heading1 db "Filename",0

Heading2 db "Size",0

FileNamePattern db "*.*",0

FileNameSortOrder dd 0

SizeSortOrder dd 0

template db "%lu",0

.data?

hInstance HINSTANCE ?

hList dd ?

hMenu dd ?

.code

start:

invoke GetModuleHandle, NULL

mov hInstance,eax

invoke WinMain, hInstance,NULL, NULL, SW_SHOWDEFAULT

invoke ExitProcess,eax

invoke InitCommonControls

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD

LOCAL wc:WNDCLASSEX

LOCAL msg:MSG

LOCAL hwnd:HWND

mov wc.cbSize,SIZEOF WNDCLASSEX

mov wc.style, NULL

mov wc.lpfnWndProc, OFFSET WndProc

mov wc.cbClsExtra,NULL

mov wc.cbWndExtra,NULL

push hInstance

pop wc.hInstance

mov wc.hbrBackground,COLOR_WINDOW+1

mov wc.lpszMenuName,IDM_MAINMENU

mov wc.lpszClassName,OFFSET ClassName

invoke LoadIcon,NULL,IDI_APPLICATION

mov wc.hIcon,eax

mov wc.hIconSm,eax

invoke LoadCursor,NULL,IDC_ARROW

mov wc.hCursor,eax

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/27 3:05:12

视频硬字幕AI去除终极方案:本地化无损修复技术详解

视频硬字幕AI去除终极方案:本地化无损修复技术详解 【免费下载链接】video-subtitle-remover 基于AI的图片/视频硬字幕去除、文本水印去除,无损分辨率生成去字幕、去水印后的图片/视频文件。无需申请第三方API,本地实现。AI-based tool for r…

作者头像 李华
网站建设 2025/12/26 20:41:51

BetterNCM插件完整教程:从零开始打造你的专属音乐工作站

BetterNCM插件完整教程:从零开始打造你的专属音乐工作站 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 还在为网易云音乐功能单一、界面单调而困扰吗?想要把普…

作者头像 李华
网站建设 2025/12/27 11:14:40

大模型注意力机制全解析:从MHA到MoBA,一文掌握七种核心算法

文章详细解析了大模型中七种注意力机制(MHA、MQA、GQA、MLA、NSA、SSA、MoBA)的原理、优缺点及应用场景。从密集计算到稀疏化,从静态模式到动态路由,展示了注意力机制在效率与表达能力间的演进历程。文章对比了各机制在工程实现与…

作者头像 李华
网站建设 2025/12/27 2:06:30

LobeChat能否实现AI调酒师?饮品配方创意与口味偏好匹配

LobeChat能否实现AI调酒师?饮品配方创意与口味偏好匹配 在一家未来感十足的酒吧里,顾客刚坐下,轻声对吧台说:“来杯清爽点的,带点柑橘味,不要太烈。” 没有翻菜单,也没有和调酒师寒暄——回应他…

作者头像 李华
网站建设 2025/12/27 19:26:35

如何快速绕过iOS激活锁:AppleRa1n完整解决方案指南

如何快速绕过iOS激活锁:AppleRa1n完整解决方案指南 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 当你面对iOS设备激活锁问题,无论是忘记Apple ID密码还是二手设备无法激活&am…

作者头像 李华
网站建设 2025/12/26 23:16:47

3分钟深入解析LLM注意力机制:轻松掌握核心原理!

简介 本文以通俗易懂的方式解释了大模型核心的Attention(注意力)机制。通过加权求和,模型有重点地关注关键信息而非平等处理所有内容。文章用淘宝购物类比解释了Q(查询)、K(键)、V(…

作者头像 李华