树型视图控件 基于iczelion教程中的例子

; treeview.asm

include common.asm

BMP_TREEVIEW = 1
CTRL_TREEVIEW = 3
CTRL_STATUS = 4

MENU_MAIN = 1

MITEM_OPEN = 3
MITEM_EXIT = 4
MITEM_HELP = 5

X_TREEVIEW = 20
Y_TREEVIEW = 20

WM_NEWTVROOT = WM_USER + 100h

.data
hInstance dd ?
fnTreeViewProc dd ?
hWndMain dd     ?

.code
_newTreeViewProc proc uses ebx esi edi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
        local   @szFileName[MAX_PATH*2]:byte ;
        local   @tvinsert:TV_INSERTSTRUCT
        local   @wfd:WIN32_FIND_DATA
        
        .if uMsg==WM_DROPFILES
                invoke  DragQueryFile, wParam, 0, addr @szFileName, sizeof @szFileName
                ; 可接受目录(视作文件),得到的文件名不带两头的引号
                ; 缓冲区不够大没有关系,API会截断过长的文件名,且保证会以0结尾
            invoke  DragFinish, wParam      ; 释放系统用来传递文件名的内存
                   
            invoke  GetFileAttributes, addr @szFileName
                .if eax & FILE_ATTRIBUTE_DIRECTORY
                        invoke  SendMessage, hWndMain, WM_NEWTVROOT, 0, addr @szFileName ;
                .endif      
        .else
                invoke  CallWindowProc, fnTreeViewProc, hWnd, uMsg, wParam, lParam
                ret ;
        .endif
        return  0
_newTreeViewProc endp

WndProc proc uses ebx esi edi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    local   @tvinsert:TV_INSERTSTRUCT
    local   @hBitmap, @hStatusBar, @hTreeView, @hItemDragTarget
    local   @tvhit:TV_HITTESTINFO
    local   @rectWindow:RECT
    local   @szBuf[256]:byte
    static  _szBuf, byte, 256 dup (?)
    static  _DragMode, dword, FALSE
        static  _hItemParent, dword, ?
        static  _hImageList, dword, ?
        static  _hDragImageList, dword, ?
        static  _hItemDragged, dword, ?
        static  _hCursorNormal, dword, ?
        static  _hCursorForbidden, dword, ?
        
        .if uMsg==WM_COMMAND
                .if lParam==0
                        mov     eax, wParam
                        and     eax, 0ffffh
                        .if eax==MITEM_OPEN
                        
                        .elseif eax==MITEM_EXIT
                                invoke  DestroyWindow, hWnd
                        .elseif eax==MITEM_HELP
                                invoke  MessageBox, hWnd, \
                                                CTXT("Just a treeview control demo."), \
                                                CTXT("about me"), MB_OK
                        .endif
                .endif
        .elseif uMsg==WM_NEWTVROOT
                invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, TVM_DELETEITEM, 0, TVI_ROOT
                invoke  _AddDirToTreeView, hWnd, CTRL_TREEVIEW, NULL, lParam
    .elseif uMsg==WM_MOUSEMOVE
        .if _DragMode
            invoke  lstrcpy, addr @szBuf, addr _szBuf
                        invoke  lstrlen, addr @szBuf
                        lea     ebx, @szBuf[eax]
                        
                        mov     eax, lParam
            mov     edx, eax
            and     eax, 0ffffh
            shr     edx, 16
            pushs   eax, edx
                        invoke  wsprintf, ebx, CTXT(" | mouse move @ (%d, %d)"), eax, edx
                        invoke  SendDlgItemMessage, hWnd, CTRL_STATUS, SB_SETTEXT, 0, addr @szBuf
                        
                        pops    eax, edx
            sub     eax, X_TREEVIEW ; 注意这些坐标是相对于treeview窗口的左上角
            sub     edx, Y_TREEVIEW    
            mov     @tvhit.pt.x, eax
                        mov     @tvhit.pt.y, edx
            invoke  ImageList_DragMove, eax, edx ; update the drag path
            
            invoke  ImageList_DragShowNolock,FALSE
                        ; Shows or hides the image being dragged
                        
            invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                        TVM_HITTEST, 0, addr @tvhit    ; check if an item is hit
                        ; TVM_HITTEST: returns the handle to the tree view item
                        ; that occupies the specified point, or NULL if no item occupies the point.
            .if eax
                                mov     @hItemDragTarget, eax
                                ;.if eax==_hItemDragged
                                ;源条目与目标条目为同一个:实际测试验证可以用句柄代替ID来标识条目
                                ; 取消高亮或是使用表示禁止的指针都会产生难看的拖动痕迹
                                
                                 ;.else
                                        invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                                        TVM_EXPAND, TVE_EXPAND, @hItemDragTarget    
                                        invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                                        TVM_SELECTITEM, TVGN_DROPHILITE, @hItemDragTarget
                                ;.endif
                        .else
                                invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                                TVM_SELECTITEM, TVGN_DROPHILITE, NULL  
                                ; 出界的话,则不显示高亮的效果。不加本句,出界了也会在最后
                                ; 拖到的那个条目处显示高亮效果
            .endif
            
                        invoke  ImageList_DragShowNolock, TRUE ;
        .endif
    .elseif uMsg==WM_LBUTTONUP
        .if _DragMode
                        invoke  GetDlgItem, hWnd, CTRL_TREEVIEW
            invoke  ImageList_DragLeave, eax
            invoke  ImageList_EndDrag
            invoke  ImageList_Destroy, _hDragImageList
            
            invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                        TVM_GETNEXTITEM, TVGN_DROPHILITE, NULL
                        ; Get the currently hilited item, i.e. the item that
                        ; is the target of a drag-and-drop operation
                        ; 其实是有高亮效果的那个条目的句柄
                        .if eax
                        ; 处理拖动
                                mov     @hItemDragTarget, eax
                                ; un-hilite the item
                                invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                                TVM_SELECTITEM, TVGN_DROPHILITE, NULL             
                                ; 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.
                                
                                invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                                TVM_SELECTITEM, TVGN_CARET, @hItemDragTarget
                                ; Sets the selection to the target of a drag-and-drop operation
                                
                        .endif
                                        
            invoke  ReleaseCapture
            mov     _DragMode, FALSE ;
        .endif
    .elseif uMsg==WM_NOTIFY
        mov     ebx, lParam
        assume  ebx:ptr NM_TREEVIEW
        .if [ebx].hdr.code==TVN_BEGINDRAG
            invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                        TVM_CREATEDRAGIMAGE, 0, [ebx].itemNew.hItem
            mov     _hDragImageList, eax
            invoke  ImageList_BeginDrag, _hDragImageList, 0, 8,8 ;鼠标指针显示在图片的正中
            ; 新建的图片列表中其实只有一张图片,若指定1,会显示暗影。
            
comment /*
msdn Community对msdn上关于ptDrag的文档的反馈:
            
ptDrag (TVN_BEGINDRAG notification code (Windows))
        Documentation says that the ptDrag member has the current cursor position in screen coordinates. This is wrong. The ptDrag has the cursor position relative to the upper left corner of the TreeView window.
        
History
    6-22-2010
    Alessandro Antonello
*/
            ; msdn 2001有误,ptDrag实为鼠标指针相对树型视图控件左上角的坐标,而非屏幕坐标
            ; ptDrag为POINT结构体(2个long:X,Y)
            invoke  wsprintf, addr _szBuf, CTXT("begin drag @ (%d, %d)"), \
                                        [ebx].ptDrag.x, [ebx].ptDrag.y
            invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                        TVM_GETNEXTITEM, TVGN_DROPHILITE, NULL
         
            invoke  GetDlgItem, hWnd, CTRL_TREEVIEW
            invoke  ImageList_DragEnter, eax, [ebx].ptDrag.x, [ebx].ptDrag.y
            
            m2m     _hItemDragged, [ebx].itemNew.hItem
            invoke  SetCapture, hWnd ;
            mov     _DragMode, TRUE ;
        .endif
        assume ebx:nothing
        .elseif uMsg==WM_SIZE
                .if wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED
                ;最大化、非最大化且非最小化造成的窗口大小改变
                        invoke  GetDlgItem, hWnd, CTRL_STATUS
                        mov     @hStatusBar, eax
                        invoke  GetWindowRect, @hStatusBar, addr @rectWindow

                        mov     eax, lParam ;新窗口客户区的宽,即状态栏的宽
                        and     eax, 0ffffh
                        
                        mov     edx, @rectWindow.bottom ; 这些坐标是屏幕坐标
                        sub     edx, @rectWindow.top  ;状态栏的高
                        mov     ebx, edx  ;
                        
                        mov     ecx, lParam
                        shr     ecx, 16 ;新窗口客户区的高
                        sub     ecx, edx ;状态栏的y
                        invoke  MoveWindow, @hStatusBar, 0, ecx, eax, edx, TRUE
                        
                        invoke  GetDlgItem, hWnd, CTRL_TREEVIEW
                        mov     @hTreeView, eax

                        mov     eax, lParam
                        mov     edx, eax
                        and     eax, 0ffffh
                        sub     eax, X_TREEVIEW*2  ; 主窗口客户区的宽度减去两端对齐的宽度
                        
                        shr     edx, 16
                        sub     edx, ebx ; 主窗口客户区的高度减去状态栏的高度,再减去两端对齐的高度
                        sub     edx, Y_TREEVIEW*2
                        invoke  MoveWindow, @hTreeView, X_TREEVIEW, Y_TREEVIEW, eax, edx, TRUE                        
                .endif
    .elseif uMsg==WM_CREATE
                invoke  InitCommonControls
                invoke  CreateStatusWindow, WS_CHILD or WS_VISIBLE, CTXT("Hi!"), hWnd, CTRL_STATUS
                
        invoke  CreateWindowEx, NULL, CTXT("SysTreeView32"), NULL, \
                                WS_CHILD or WS_VISIBLE or TVS_HASLINES or TVS_HASBUTTONS or TVS_LINESATROOT, \
                                X_TREEVIEW, Y_TREEVIEW, 150, 300, hWnd, CTRL_TREEVIEW, hInstance,NULL
                mov     ebx, eax
        invoke    DragAcceptFiles, eax, TRUE ;
        invoke  SetWindowLong, ebx, GWL_WNDPROC, offset _newTreeViewProc
        mov     fnTreeViewProc, eax
        
        invoke  ImageList_Create, 16, 16, ILC_COLOR4, 2, 10 ; ILC_COLOR4: 4-bit (16-color)
        mov     _hImageList, eax
        invoke  LoadBitmap, hInstance, BMP_TREEVIEW
        mov     @hBitmap, eax
        invoke  ImageList_Add, _hImageList, eax, NULL
        invoke  DeleteObject, @hBitmap ; always delete the bitmap resource
        ; since it will not be used anymore
    
        invoke  SendDlgItemMessage, hWnd, CTRL_TREEVIEW, \
                                TVM_SETIMAGELIST, TVSIL_NORMAL, _hImageList
    
        ; 用于拖动的时候
        ;invoke  LoadCursor, 0, IDC_NO ;Slashed(斜线) circle
                ;mov     _hCursorForbidden, eax    
    .elseif uMsg==WM_DESTROY
        invoke PostQuitMessage, 0
    .else
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam        
        ret
    .endif
    xor     eax,eax
    ret
WndProc endp

start   proc
    local   @wc:WNDCLASSEX
    local   @msg:MSG
    
    invoke  GetModuleHandle, NULL
    mov     hInstance, eax

    mov     @wc.cbSize, sizeof @wc
    mov     @wc.style, CS_HREDRAW or CS_VREDRAW
    mov     @wc.lpfnWndProc, offset WndProc
    mov     @wc.cbClsExtra, 0
    mov     @wc.cbWndExtra, 0
    push    hInstance
    pop     @wc.hInstance
    mov     @wc.hbrBackground, COLOR_APPWORKSPACE+1
    mov     @wc.lpszMenuName, MENU_MAIN
    mov     @wc.lpszClassName, CTXT("SimpleWindow")
    invoke  LoadIcon, 0, IDI_APPLICATION
    mov     @wc.hIcon, eax
    mov     @wc.hIconSm, eax
    invoke  LoadCursor, 0, IDC_ARROW
    mov     @wc.hCursor, eax
    invoke  RegisterClassEx, addr @wc
    
    invoke  CreateWindowEx, WS_EX_CLIENTEDGE, CTXT("SimpleWindow"), CTXT("Tree View Demo"),\
                        WS_OVERLAPPEDWINDOW or WS_VISIBLE, \
                        CW_USEDEFAULT, CW_USEDEFAULT,200,400, \
                        NULL, NULL, hInstance, NULL
    mov     hWndMain, eax
    
    .while 1
        invoke GetMessage, addr @msg, NULL, 0, 0
        .break .if !eax
        invoke TranslateMessage, addr @msg
        invoke DispatchMessage, addr @msg
    .endw

    invoke  ExitProcess, @msg.wParam
start   endp


        end     start

------------------------------------------------------------------------

; 把一个目录及其其下的子目录加到树型视图控件hItem指定的条目下
_AddDirToTreeView proc uses ebx esi hDlg, idTreeView, hItem, pszPathName
        local   @szFileName[MAX_PATH*8]:byte ;有溢出的风险
        local   @tvinsert:TV_INSERTSTRUCT
        local   @wfd:WIN32_FIND_DATA
        
        m2m     @tvinsert.hParent, hItem
        mov     @tvinsert.hInsertAfter, TVI_SORT ;按字母序排列
        mov     @tvinsert.item.imask,TVIF_TEXT or TVIF_IMAGE or TVIF_SELECTEDIMAGE

        invoke  _GetFileName, pszPathName
        mov     @tvinsert.item.pszText, eax
        mov     @tvinsert.item.iImage, 0
        mov     @tvinsert.item.iSelectedImage, 1
        invoke  SendDlgItemMessage, hDlg, idTreeView, TVM_INSERTITEM,0,addr @tvinsert
        mov     ebx, eax

        invoke  lstrcpy, addr @szFileName, pszPathName
        invoke  lstrcat, addr @szFileName, CTXT("\*")
        invoke  FindFirstFile, addr @szFileName, addr @wfd ;用来查找指定名字的文件或目录
        mov     esi, eax

        .while 1
                .if @wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
                        invoke  lstrcmp, addr @wfd.cFileName, CTXT(".") ; 表示本目录的条目
                        .if !eax
                                jmp     @next
                        .endif
                        
                        invoke  lstrcmp, addr @wfd.cFileName, CTXT("..") ; 表示父目录的条目
                        .if !eax
                                jmp     @next
                        .endif
                        
                        invoke  lstrcpy, addr @szFileName, pszPathName
                        invoke  lstrcat, addr @szFileName, CTXT("\")
                        invoke  lstrcat, addr @szFileName, addr @wfd.cFileName
                        invoke  _AddDirToTreeView, hDlg, idTreeView, ebx, addr @szFileName
                .endif
        @next:
                invoke  FindNextFile, esi, addr @wfd
                .if !eax
                        ;invoke   GetLastError
                        ;.if eax==ERROR_NO_MORE_FILES
                        
                        ;.endif
                        .break
                .endif
        .endw

        invoke  FindClose, esi
        ret
_AddDirToTreeView endp




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值