上一篇 | 下一篇

树型视图控件

发布: 2008-6-26 22:55 | 作者: admin | 来源: | 查看: 6次

分析:

在处理消息WM_CREATE的代码中,您可以创建树型视图控件。

invoke CreateWindowEx,NULL,ADDR TreeViewClass,NULL,\

WS_CHILD+WS_VISIBLE+TVS_HASLINES+TVS_HASBUTTONS+TVS_LINESATROOT,0,\

0,200,400,hWnd,NULL,\

hInstance,NULL

注意: TVS_xxxx 是树型视图所特有的风格。

invoke ImageList_Create,16,16,ILC_COLOR16,2,10

mov hImageList,eax

invoke LoadBitmap,hInstance,IDB_TREE

mov hBitmap,eax

invoke ImageList_Add,hImageList,hBitmap,NULL

invoke DeleteObject,hBitmap

invoke SendMessage,hwndTreeView,TVM_SETIMAGELIST,0,hImageList

接下来,您可以创建一个空的图像列表,该图像列表容纳的是以像素为单位16x16大小和16位深度的图像,该图像列表初始包含两幅图像,最大可以容纳10幅。然后我们从资源中加载图像,并把它们放到图像列表中去。随后我们删除掉图像的句柄,因为我们不需要再用到它。设置好图像列表后,我们通过发送消息TVM_SETIMAGELIST把它和树型视图控件联系起来。

mov tvinsert.hParent,NULL

mov tvinsert.hInsertAfter,TVI_ROOT

mov tvinsert.u.item.imask,TVIF_TEXT+TVIF_IMAGE+TVIF_SELECTEDIMAGE

mov tvinsert.u.item.pszText,offset Parent

mov tvinsert.u.item.iImage,0

mov tvinsert.u.item.iSelectedImage,1

invoke SendMessage,hwndTreeView,TVM_INSERTITEM,0,addr tvinsert

现在把项目插入到树型视图控件中去,首先我们从根项目开始。因为是根项目,所以成员变量hParent是NULL,hInsertAfter是TVI_ROOT。imask指定TV_ITEM结构体变量中的pszText,iImage和iSelectedImage三个成员变量的值是有效的。我们应该给这三个成员变量赋上正确的值。其中pszText显示项目的名称,iImage是图像列表中图像的索引号,该图像显示在未选中的项目名称的左边,iSelectedImage是选中的项目的图像索引号。设置好了这些值后,我们发送TVM_INSERTITEM消息给树型视图控件来把根项目加入到树型视图控件中去。

mov hParent,eax

mov tvinsert.hParent,eax

mov tvinsert.hInsertAfter,TVI_LAST

mov tvinsert.u.item.pszText,offset Child1

invoke SendMessage,hwndTreeView,TVM_INSERTITEM,0,addr tvinsert

mov tvinsert.u.item.pszText,offset Child2

invoke SendMessage,hwndTreeView,TVM_INSERTITEM,0,addr tvinsert

加入完根项目后,我们再加入子项目。这时的成员变量hParent是其父项目的句柄,hInsertAfter的值是TVI_LAST。至于选中和非选中时用的图像是一样的,所以我们无需更改其它变量的值。

.elseif uMsg==WM_NOTIFY

mov edi,lParam

assume edi:ptr NM_TREEVIEW

.if [edi].hdr.code==TVN_BEGINDRAG

invoke SendMessage,hwndTreeView,TVM_CREATEDRAGIMAGE,0,[edi].itemNew.hItem

mov hDragImageList,eax

invoke ImageList_BeginDrag,hDragImageList,0,0,0

invoke ImageList_DragEnter,hwndTreeView,[edi].ptDrag.x,[edi].ptDrag.y

invoke SetCapture,hWnd

mov DragMode,TRUE

.endif

assume edi:nothing

当用户拖动项目时,树型视图控件将发送WM_NOTIFY消息给它的父窗口,子消息号是TVN_BEGINDRAG。在lPAram中是指向结构体NM_TREEVIEW 的指针,该结构体包含了一些附加信息。我们把lParam的值放到edi寄存器中,这样就可以把edi作为一个指针来使用。“assume edi:ptr NM_TREEVIEW ”语句用来告诉编译器MASM把edi作为指向NM_TREEVIEW 的结构体的变量使用。我们通过发送消息TVM_CREATEDRAGIMAGE来创建一个拖动的图像。它将返回一个新创建的图像列表的句柄,该图像列表中包含拖动中的图像。我们调用ImageList_BeginDrag函数设置拖动图像的热点。调用ImageList_DragEnter函数进入操作。该函数会在特定位置显示拖动中的图像。起初显示的位置我们设在结构体NM_TREEVIEW中的成员变量ptDrag所指的位置。我们锁定鼠标的输入,并设置标志变量,表示我们进入了拖拉操作。

.elseif uMsg==WM_MOUSEMOVE

.if DragMode==TRUE

mov eax,lParam

and eax,0ffffh

mov ecx,lParam

shr ecx,16

mov tvhit.pt.x,eax

mov tvhit.pt.y,ecx

invoke ImageList_DragMove,eax,ecx

invoke ImageList_DragShowNolock,FALSE

invoke SendMessage,hwndTreeView,TVM_HITTEST,NULL,addr tvhit

.if eax!=NULL

invoke SendMessage,hwndTreeView,TVM_SELECTITEM,TVGN_DROPHILITE,eax

.endif

invoke ImageList_DragShowNolock,TRUE

.endif

现在我们来看看WM_MOUSEMOVE消息的处理过程。当用户拖动图像时,我们的父窗口将接收到WM_MOUSEMOVE。为了响应这些消息,我们调用ImageList_DragMove来更新更新图像的位置。然后我们发送消息TVM_HITTEST给列表视图控件看看拖拉中的图像是否正好经过某些项目的上面,当然还要附带传递坐标位置等信息。如果经过的话,我们发送消息TVM_SELECTITEM并附带TVGN_DROPHILITE标志给树型视图控件,后者将会高亮度显示正被经过的项目。在高亮度显示的过程中,我们隐藏掉拖动中的图像免得显示的图像难看。

.elseif uMsg==WM_LBUTTONUP

.if DragMode==TRUE

invoke ImageList_DragLeave,hwndTreeView

invoke ImageList_EndDrag

invoke ImageList_Destroy,hDragImageList

invoke SendMessage,hwndTreeView,TVM_GETNEXTITEM,TVGN_DROPHILITE,0

invoke SendMessage,hwndTreeView,TVM_SELECTITEM,TVGN_CARET,eax

invoke SendMessage,hwndTreeView,TVM_SELECTITEM,TVGN_DROPHILITE,0

invoke ReleaseCapture

mov DragMode,FALSE

.endif

当用户释放鼠标左键后,拖拉操作就可以结束了。我们调用ImageList_DragLeave,ImageList_EndDrag和ImageList_Destroy来结束拖拉操作模式。为了使得树形视图控件好看,我们检查最后高亮度显示的项目,并且选中它。我们还必须使得其不高亮度显示,否则其它的项目被选中时就不能高亮度显示了。最后我们释放对鼠标输入事件的捕获。

字号: | 推荐给好友

65/6<123456>

评分:0

我来说两句