汇编教程之树型视图控件
2008-04-28 09:33:29 来源:WEB开发网分析:
在处理消息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来结束拖拉操作模式。为了使得树形视图控件好看,我们检查最后高亮度显示的项目,并且选中它。我们还必须使得其不高亮度显示,否则其它的项目被选中时就不能高亮度显示了。最后我们释放对鼠标输入事件的捕获。
更多精彩
赞助商链接