📄 lion-tutorial19.htm
字号:
<li> <b>TVGN_NEXT </b>Retrieves the next sibling item.</li>
<li> <b>TVGN_NEXTVISIBLE</b> Retrieves the next visible item that follows
the specified item. The specified item must be visible. Use the TVM_GETITEMRECT
message to determine whether an item is visible.</li>
<li> <b>TVGN_PARENT</b> Retrieves the parent of the specified item.</li>
<li> <b>TVGN_PREVIOUS</b> Retrieves the previous sibling item.</li>
<li> <b>TVGN_PREVIOUSVISIBLE</b> Retrieves the first visible item that precedes
the specified item. The specified item must be visible. Use the TVM_GETITEMRECT
message to determine whether an item is visible.</li>
<li> <b>TVGN_ROOT</b> Retrieves the topmost or very first item of the tree-view
control.</li>
</ul>
</ul>
You can see that, you can retrieve the handle to the tree view item you are interested
in from this message. <b>SendMessage</b> returns the handle to the tree view item
if successful. You can then fill the returned handle into hItem member of <b>TV_ITEM
</b>to be used with <b>TVM_GETITEM</b> message.
<h4> Drag and Drop Operation in tree view control</h4>
This part is the reason I decided to write this tutorial. When I tried to follow
the example in win32 api reference (the win32.hlp from InPrise), I was very frustrated
because the vital information is lacking. From trial and error, I finally figured
out how to implement drag & drop in a tree view control and I don't want anyone
to walk the same path as myself. <br>
Below is the steps in implementing drag & drop operation in a tree view control.
<ol>
<li> When the user tries to drag an item, the tree view control sends <b>TVN_BEGINDRAG</b>
notification to the parent window. You can use this opportunity to create
a drag image which is the image that will be used to represent the item while
it's being dragged. You can send <b>TVM_CREATEDRAGIMAGE</b> to the tree view
control to tell it to create a default drag image from the image that is currently
used by the item that will be dragged. The tree view control will create an
image list with just one drag image and return the handle to that image list
to you.</li>
<li> After the drag image is created, you specify the hotspot of the drag image
by calling <b>ImageList_BeginDrag.</b></li>
<ol>
<b>ImageList_BeginDrag PROTO himlTrack:DWORD, \</b> <br>
<b>
iTrack:DWORD , \</b> <br>
<b>
dxHotspot:DWORD, \</b> <br>
<b>
dyHotspot:DWORD</b> <br>
<b>himlTrack</b> is the handle to the image list that contains the drag image.
<br>
<b>iTrack</b> is the index into the image list that specifies the drag image
<br>
<b>dxHotspot</b> specifies the relative distance of the hotspot in horizontal
plance in the drag image since this image will be used in place of the mouse
cursor, so we need to specify which part of the image is the hotspot. <br>
<b>dyHotspot</b> specifies the relative distance of the hotspot in the vertical
plane. <br>
Normally, iTrack would be 0 if you tell the tree view control to create the
drag image for you. and dxHotspot and dyHotspot can be 0 if you want the left
upper corner of the drag image to be the hotspot.
</ol>
<li> When the drag image is ready to be displayed, we call <b>ImageList_DragEnter</b>
to display the drag image in the window.</li>
<ol>
<b>ImageList_DragEnter PROTO hwndLock:DWORD, x:DWORD, y:DWORD</b> <br>
<b>hwndLock</b> is the handle of the window that owns the drag image. The
drag image will not be able to move outside that window. <br>
<b>x and y</b> are the x-and y-coordinate of the place where the drag image
should be initially displayed. Note that these values are relative to the
left upper corner of the window, not the client area.
</ol>
<li> Now that the drag image is displayed on the window, you will have to support
the drag operation in the tree view control. However, there is a little problem
here. We have to monitor the drag path with <b>WM_MOUSEMOVE</b> and the drop
location with <b>WM_LBUTTONUP</b> messages. However, if the drag image is
over some other child windows, the parent window will never receive any mouse
message. The solution is to capture the mouse input with <b>SetCapture</b>.
Using the call, the mouse messages will be directed to the specified window
regardless of where the mouse cursor is.</li>
<li> Within <b>WM_MOUSEMOVE</b> handler, you will update the drag path with
ImageList_DragMove call. This function moves the image that is being dragged
during a drag-and-drop operation. Furthermore, if you so desire, you can hilite
the item that the drag image is over by sending <b>TVM_HITTEST</b> to check
if the drag image is over some item. If it is, you can send <b>TVM_SELECTITEM</b>
with <b>TVGN_DROPHILITE</b> flag to hilite that item. Note that before sending
<b>TVM_SELECTITEM </b>message, you must hide the drag image first else your
drag image will leave ugly traces. You can hide the drag image by calling
ImageList_DragShowNolock and, after the hilite operation is finished, call
ImageList_DragShowNolock again to show the drag image.</li>
<li> When the user releases the left mouse button, you must do several things.
If you hilite an item, you must un-hilite it by sending <b>TVM_SELECTITEM</b>
with <b>TVGN_DROPHILITE </b>flag again, but this time, lParam MUST be zero.
If you don't un-hilite the item, you will get a strange effect: when you select
some other item, that item will be enclosed by a rectangle but the hilite
will still be on the last hilited item. Next, you must call <b>ImageList_DragLeave</b>
followed by <b>ImageList_EndDrag</b>. You must release the mouse by calling
<b>ReleaseCapture</b>. If you create an image list, you must destroy it by
calling <b>ImageList_Destroy</b>. After that, you can go on with what your
program wants to do when the drag & drop operation is completed.</li>
</ol>
<h3> Code sample:</h3>
<b>.386</b> <br>
<b>.model flat,stdcall</b> <br>
<b>option casemap:none</b> <br>
<b>include \masm32\include\windows.inc</b> <br>
<b>include \masm32\include\user32.inc</b> <br>
<b>include \masm32\include\kernel32.inc</b> <br>
<b>include \masm32\include\comctl32.inc</b> <br>
<b>include \masm32\include\gdi32.inc</b> <br>
<b>includelib \masm32\lib\gdi32.lib</b> <br>
<b>includelib \masm32\lib\comctl32.lib</b> <br>
<b>includelib \masm32\lib\user32.lib</b> <br>
<b>includelib \masm32\lib\kernel32.lib</b>
<p><b>WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD</b> <br>
<b>.const</b> <br>
<b>IDB_TREE equ 4006
; ID of the bitmap resource</b> <br>
<b>.data</b> <br>
<b>ClassName db "TreeViewWinClass",0</b> <br>
<b>AppName db "Tree View Demo",0</b> <br>
<b>TreeViewClass db "SysTreeView32",0</b> <br>
<b>Parent db "Parent Item",0</b> <br>
<b>Child1 db "child1",0</b> <br>
<b>Child2 db "child2",0</b> <br>
<b>DragMode dd FALSE
; a flag to determine if we are in drag mode</b>
<p><b>.data?</b> <br>
<b>hInstance HINSTANCE ?</b> <br>
<b>hwndTreeView dd ?
; handle of the tree view control</b> <br>
<b>hParent dd ?
; handle of the root tree view item</b> <br>
<b>hImageList dd ?
; handle of the image list used in the tree view control</b> <br>
<b>hDragImageList dd ? ; handle
of the image list used to store the drag image</b>
<p><b>.code</b> <br>
<b>start:</b> <br>
<b> invoke GetModuleHandle, NULL</b> <br>
<b> mov hInstance,eax</b> <br>
<b> invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT</b>
<br>
<b> invoke ExitProcess,eax</b> <br>
<b> invoke InitCommonControls</b>
<p><b>WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD</b>
<br>
<b> LOCAL wc:WNDCLASSEX</b> <br>
<b> LOCAL msg:MSG</b> <br>
<b> LOCAL hwnd:HWND</b> <br>
<b> mov wc.cbSize,SIZEOF WNDCLASSEX</b> <br>
<b> mov wc.style, CS_HREDRAW or CS_VREDRAW</b>
<br>
<b> mov wc.lpfnWndProc, OFFSET WndProc</b> <br>
<b> mov wc.cbClsExtra,NULL</b> <br>
<b> mov wc.cbWndExtra,NULL</b> <br>
<b> push hInst</b> <br>
<b> pop wc.hInstance</b> <br>
<b> mov wc.hbrBackground,COLOR_APPWORKSPACE</b>
<br>
<b> mov wc.lpszMenuName,NULL</b> <br>
<b> mov wc.lpszClassName,OFFSET ClassName</b>
<br>
<b> invoke LoadIcon,NULL,IDI_APPLICATION</b> <br>
<b> mov wc.hIcon,eax</b> <br>
<b> mov wc.hIconSm,eax</b> <br>
<b> invoke LoadCursor,NULL,IDC_ARROW</b> <br>
<b> mov wc.hCursor,eax</b> <br>
<b> invoke RegisterClassEx, addr wc</b> <br>
<b> invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR
AppName,\ WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,\</b>
<br>
<b> CW_USEDEFAULT,200,400,NULL,NULL,\</b>
<br>
<b> hInst,NULL</b>
<br>
<b> mov hwnd,eax</b> <br>
<b> .while TRUE</b> <br>
<b> invoke GetMessage, ADDR msg,NULL,0,0</b>
<br>
<b> .BREAK .IF (!eax)</b> <br>
<b> invoke TranslateMessage, ADDR
msg</b> <br>
<b> invoke DispatchMessage, ADDR msg</b>
<br>
<b> .endw</b> <br>
<b> mov eax,msg.wParam</b> <br>
<b> ret</b> <br>
<b>WinMain endp</b>
<p><b>WndProc proc uses edi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM</b>
<br>
<b> LOCAL tvinsert:TV_INSERTSTRUCT</b> <br>
<b> LOCAL hBitmap:DWORD</b> <br>
<b> LOCAL tvhit:TV_HITTESTINFO</b> <br>
<b> .if uMsg==WM_CREATE</b> <br>
<b> invoke CreateWindowEx,NULL,ADDR
TreeViewClass,NULL,\</b> <br>
<b> WS_CHILD+WS_VISIBLE+TVS_HASLINES+TVS_HASBUTTONS+TVS_LINESATROOT,0,\</b>
<br>
<b> 0,200,400,hWnd,NULL,\</b>
<br>
<b> hInstance,NULL
; Create the tree view control</b> <br>
<b> mov hwndTreeView,eax</b> <br>
<b> invoke ImageList_Create,16,16,ILC_COLOR16,2,10
; create the associated image list</b> <br>
<b> mov hImageList,eax</b> <br>
<b> invoke LoadBitmap,hInstance,IDB_TREE
; load the bitmap from the resource</b> <br>
<b> mov hBitmap,eax</b> <br>
<b> invoke ImageList_Add,hImageList,hBitmap,NULL
; Add the bitmap into the image list</b> <br>
<b> invoke DeleteObject,hBitmap
; always delete the bitmap resource</b> <br>
<b> invoke SendMessage,hwndTreeView,TVM_SETIMAGELIST,0,hImageList</b>
<br>
<b> mov tvinsert.hParent,NULL</b>
<br>
<b> mov tvinsert.hInsertAfter,TVI_ROOT</b>
<br>
<b> mov tvinsert.item.imask,TVIF_TEXT+TVIF_IMAGE+TVIF_SELECTEDIMAGE</b>
<br>
<b> mov tvinsert.item.pszText,offset
Parent</b> <br>
<b> mov tvinsert.item.iImage,0</b>
<br>
<b> mov tvinsert.item.iSelectedImage,1</b>
<br>
<b> invoke SendMessage,hwndTreeView,TVM_INSERTITEM,0,addr
tvinsert</b> <br>
<b> mov hParent,eax</b> <br>
<b> mov tvinsert.hParent,eax</b> <br>
<b> mov tvinsert.hInsertAfter,TVI_LAST</b>
<br>
<b> mov tvinsert.item.pszText,offset
Child1</b> <br>
<b> invoke SendMessage,hwndTreeView,TVM_INSERTITEM,0,addr
tvinsert</b> <br>
<b> mov tvinsert.item.pszText,offset
Child2</b> <br>
<b> invoke SendMessage,hwndTreeView,TVM_INSERTITEM,0,addr
tvinsert</b> <br>
<b> .elseif uMsg==WM_MOUSEMOVE</b> <br>
<b> .if DragMode==TRUE</b> <br>
<b> mov eax,lParam</b>
<br>
<b> and eax,0ffffh</b>
<br>
<b> mov ecx,lParam</b>
<br>
<b> shr ecx,16</b>
<br>
<b> mov tvhit.pt.x,eax</b>
<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -