分析: 在处理消息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来结束拖拉操作模式。为了使得树形视图控件好看,我们检查最后高亮度显示的项目,并且选中它。我们还必须使得其不高亮度显示,否则其它的项目被选中时就不能高亮度显示了。最后我们释放对鼠标输入事件的捕获。
上一篇:工具提示控件
下一篇:多文档界面(MDI)
|