列表视图控件介绍
2007-05-02 09:32:00 来源:WEB开发网我们将让用户通过菜单来选择它想要的显示方式。这样我们必须先得到菜单的句柄。我了让用户跟踪当前的视图,我们在菜单中放入一组单选按钮。我们可以调用CheckMenuRadioItem函数,该函数将把一个单选按钮放到一个菜单项前。
注意我们创建列表视图控件时把它的宽度和高度都设成为0。当父窗口改变大小时,它将同时改变大小。这样我们可以让列表视图总是随着主窗口改变。子我们的例子中,我们让列表视图填充整个客户区。
.elseif uMsg==WM_SIZE
mov eax,lParam
mov edx,eax
and eax,0ffffh
shr edx,16
invoke MoveWindow,hList, 0, 0, eax,edx,TRUE
当父窗口接收到了WM_SIZE消息后,lParam的底字部分包含了客户区新的宽和高。让后我们调用MoveWindow来改变列表视图控件的大小使得它覆盖整个的客户区。
当用户通过菜单选择了一种选择方式,我们必须相应地改变列表视图中的显示方式。我们调用SetWindowLong函数来设定新的风格。
.elseif uMsg==WM_COMMAND
.if lParam==0
invoke GetWindowLong,hList,GWL_STYLE
and eax,not LVS_TYPEMASK
首先得到当前的风格,然后清除旧的风格。LVS_TYPEMASK 是LVS_ICON+LVS_SMALLICON+LVS_LIST+LVS_REPORT四种风格的集合。这样当我们用当前的风格“与”“not LVS_TYPEMASK”就等于清除了当前的显示风格。
在设计菜单时,我们使用了一些小技巧。我们包显示风格的常数串当作菜单的ID号。
IDM_ICON equ LVS_ICON
IDM_SMALLICON equ LVS_SMALLICON
IDM_LIST equ LVS_LIST
IDM_REPORT equ LVS_REPORT
这样当父窗口接收到WM_COMMAND消息时,希望显示的风格值会当成菜单的ID号传递过来。
mov edx,wParam
and edx,0FFFFh
在wParam中的低字部分是欲显示的风格,我们所需要做的只是把高字部分清0。
push edx
or eax,edx
我们把希望显示的风格加到列表视图的风格中去(已经去除了旧的风格)。
invoke SetWindowLong,hList,GWL_STYLE,eax
调用SetWindowLong函数来设定新的风格。
pop edx
invoke CheckMenuRadioItem,hMenu,IDM_ICON,IDM_LIST, edx,MF_CHECKED
.endif
我们需要在被选择的显示方式前放入单选按钮。如果要排序,我们必须处理WM_NOTIFY消息。
.elseif uMsg==WM_NOTIFY
push edi
mov edi,lParam
assume edi:ptr NMHDR
mov eax,[edi].hwndFrom
.if eax==hList
当我们接收到了WM_NOTIFY 消息后,lParam包含了指向NMHDR型结构体变量的指针。我们通过把列表视图控件的值和NMHDR型结构体变量中的hwndFrom成员变量的值比较来判断,如果相等的话我们就可以确定消息是列表视图控件发送的。
.if [edi].code==LVN_COLUMNCLICK
assume edi:ptr NM_LISTVIEW
如果通知消息是列表视图控件发送的,我们检测该消息是否是LVN_COLUMNCLICK。如果是,它意味着用户点击了列标题条。在接收到LVN_COLUMNCLICK消息后,我们假设lParam参数包含NM_LISTVIEW型结构体变量的指针,NM_LISTVIEW型结构体是NMHDR型结构体的扩展。我们需要知道用户单击了那一列,在iSubItem中的值即是列号,列的编号是从0开始的。
.if [edi].iSubItem==1
.if SizeSortOrder==0 || SizeSortOrder==2
在这里iSubItem的值是1,它表示用户点击的是第二列,即文件的大小。我们用状态变量来保持当前的排序顺序。0代表不用排序,1代表升序,2代表降序。如果该列中的项目/子项目以前没有排序或为降序,我们就把它设成升序。
invoke SendMessage,hList,LVM_SORTITEMS,1,addr CompareFunc
我们发送消息LVM_SORTITEMS给列表视图控件,在wParam中传递1,在lParam中传递比较函数的参数。注意wParam中的值是用户定义的,用户可以按自己的需要来解释,这里我们把它用作排序的方法。我们先来看看比较函数:
CompareFunc proc uses edi lParam1:DWORD, lParam2:DWORD, SortType:DWORD
LOCAL buffer[256]:BYTE
LOCAL buffer1[256]:BYTE
LOCAL lvi:LV_ITEM
mov lvi.imask,LVIF_TEXT
lea eax,buffer
mov lvi.pszText,eax
mov lvi.cchTextMax,256
列表视图控件将传递需要比较的两个项目的lParam(LV_ITEM型结构体变量的成员变量)比较函数。您还记得吗?我们在lParam中放置了醒目的索引号。这样我们利用这些索引号查询列表视图来得到项目信息。我们需要的消息是项目/子项目的标签文本。为此我们准备好LV_ITEM 型结构体变量并在iMask中设置标志位LVIF_TEXT ,在pszText中设置缓冲区的地址,在cchTextMax中设置缓冲区的大小。
.if SortType==1
mov lvi.iSubItem,1
invoke SendMessage,hList,LVM_GETITEMTEXT,lParam1,addr lvi
如果SortType的值为1或2,我们知道点击了那一列,1代表根据文件的大小按升序排列所有的项目。2的意思相反。这样我们指定iSubItem为1(代表文件大小列)然后发送LVM_GETITEMTEXT 消息给列表视图控件来得到在项目的标签文本串。
invoke String2Dword,addr buffer
mov edi,eax
调用子定义的String2Dword函数来把字符串转换成一个DWORD值。它将在eax中返回转换后的值,我们把它保存在edi中以便以后比较用。
invoke SendMessage,hList,LVM_GETITEMTEXT,lParam2,addr lvi
invoke String2Dword,addr buffer
sub edi,eax
mov eax,edi
对lParam2 中的值做同样的操作。当我们得到了两个文件的大小后,就可以比较它们了。比较的规则如下:
如果第一个项目放在前面,在eax中返回一个负值
如果第二个项目放在前面,在eax中返回一个正值
如果相等,在eax中返回0
在我们这里,我们想按升序排列,所以我们只要简单地将第二个项目的文件大小减去第一个项目的文件大小,然后返回放在eax中的值。
.elseif SortType==3
mov lvi.iSubItem,0
invoke SendMessage,hList,LVM_GETITEMTEXT,lParam1,addr lvi
invoke lstrcpy,addr buffer1,addr buffer
invoke SendMessage,hList,LVM_GETITEMTEXT,lParam2,addr lvi
invoke lstrcmpi,addr buffer1,addr buffer
当用户点击文件名字列时,我们必须比较文件的名字。我们先得到文件的名字,然后调用lstrcmpi函数来比较,然后只要简单返回lstrcmpi的值,因为该函数比较使用的规则和我们的相同。
当项目排序后,我们调用UpdateParam函数来更新所有项目的lParam的值来反应出最新的改变。
invoke UpdatelParam
mov SizeSortOrder,1
该函数简单地枚举列表视图中所有的项目并且把它们lParam更新成项目的索引号。
.elseif [edi].code==NM_DBLCLK
invoke ShowCurrentFocus
.endif
如果用户双击某个项目时,我们将显示一个消息框,上面有该项目的有关标签值。我们必须检查NMHDR 中的code值是否是 NM_DBLCLK。如果是,我们就得到它的标签值并显示在一个消息框中。
ShowCurrentFocus proc
LOCAL lvi:LV_ITEM
LOCAL buffer[256]:BYTE
invoke SendMessage,hList,LVM_GETNEXTITEM,-1, LVNI_FOCUSED
我们是增么怎么知道某个项目被双击的呢?当单击或双击某个项目时,它的状态被设成“焦点”。即使有多个项目被选中,也仅有一个项目有焦点。我们的工作就是去找到那个有焦点的项目。我们发送LVM_GETNEXTITEM消息给列表视图控件,在lParam中指定期望的状态。如果wParam中时-1的话,表示要搜索所有的项目。有焦点的项目第索引号在eax中返回。
mov lvi.iItem,eax
mov lvi.iSubItem,0
mov lvi.imask,LVIF_TEXT
lea eax,buffer
mov lvi.pszText,eax
mov lvi.cchTextMax,256
invoke SendMessage,hList,LVM_GETITEM,0,addr lvi
发送LVM_GETITEM消息来得到标签。
invoke MessageBox,0, addr buffer,addr AppName,MB_OK
最后我们在一个消息框中显示标签。
如果想在列表视图控件中显示图标,您可以阅读关于树型视图控件的课程。它们的步骤基本上是一样的。
- ››控件一:Gallery 之无限循环的问题
- ››控件一:Gallery 之基础用法
- ››视图的架构刷新和绑定
- ››列表页文章新窗口打开方式设置
- ››视图简介
- ››列表视图控件介绍
- ››控件“树”中多选拖放功能的实现
- ››控件如何传递自定义struct
- ››列表显示命令
- ››控件style你知我知
- ››控件移动类的实现之一
- ››控件移动类的实现之二
更多精彩
赞助商链接