TreeView 控件使用

  TreeView控件是最常用的控件之一,最近研究了一下,一开始是一点头绪都没有,不过多研究一下就越来越清晰了.呵呵.这篇文章也算是我自己的拾遗吧.
  虽然windows里的TreeView控件不像Java的MVC结构那样让人感觉很清晰,但是它还是提供了一系列的消息来对TreeView本身的数据结构的处理,所以用熟了的话,也不是很麻烦.其实也有很多相关的宏,但是这些宏好像windows汇编无法使用.但是用宏的话就没有意思了,自己去实现一下也是很不错的嘛.呵呵.
  说到树型视图控件,要提到的就是TVITEM(TVITEMEX)结构体,这个结构体是一个项目(元素),它是TreeView的重要组成部分.它的定义为:
typedef struct tagTVITEM{
UINT mask;
HTREEITEM hItem;
UINT state;
UINT stateMask;
LPTSTR pszText;
int cchTextMax;
int iImage;
int iSelectedImage;
int cChildren;
LPARAM lParam;
} TVITEM, FAR *LPTVITEM;
创建TreeView可以简单地用createwindowex函数.而对它的操作,主要是对ITEM的操作,这里简单列一些操作.
  • 插入,删除和修改ITEM
  •   插入一个ITEM,需要填写TVINSERTSTRUCT结构体.这个结构体包含一个Parent句柄,一个插入位置标志和一个TVITEM结构体.我们并不用全部填写.先看TVINSERTSTRUCT结构体,然后再说明
    typedef struct tagTVINSERTSTRUCT {
    HTREEITEM hParent;
    HTREEITEM hInsertAfter;
    #if (_WIN32_IE >= 0x0400)
    union
    {
    TVITEMEX itemex;
    TVITEM item;
    } DUMMYUNIONNAME;
    #else
    TVITEM item;
    #endif
    } TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
    hParent是指定这个ITEM的父节点,如果它是根节点,可以为TVI_ROOT或NULL.
    hInsertAfter是插入到哪个节点之后,是一个ITEM的句柄,可以用TVI_FIRST等常量
    TVITEM里指定要加入项目的属性,并不是所有的都要设定,而是看mask和statemask.如果设置mask为TVIF_TEXT,那么说明这个ITEM是纯TEXT型的,我们只要指定pszText和cchTextMax就行了.可以多种mask值或起来作为参数.如果是TVIF_IMAGE的,必须要为这个TreeView设置一个ImageList.
    下面是一个插入ITEM的片段:
    local u:USER
    push hTreeWindow
    pop hTreeWin
    invoke SendMessage,hTreeWindow,TVM_SETITEMHEIGHT,26,0
    invoke ImageList_Create,24,24,ILC_COLOR24,5,2
    mov hImageList,eax
    invoke LoadBitmap,hInstance,IDC_STATEBIT
    push eax
    invoke ImageList_Add,hImageList,eax,NULL
    pop eax
    invoke DeleteObject,eax
    invoke SendMessage,hTreeWindow,TVM_SETIMAGELIST,NULL,hImageList
    invoke RtlZeroMemory,addr insertTNode.item,sizeof TVITEM
    mov insertTNode.hParent,NULL
    mov insertTNode.hInsertAfter,TVI_ROOT
    mov insertTNode.item.imask,TVIF_TEXT+TVIF_IMAGE+TVIF_SELECTEDIMAGE+TVIF_STATE
    mov insertTNode.item.pszText,offset parentText
    mov insertTNode.item.iImage,3
    mov insertTNode.item.iSelectedImage,3
    mov insertTNode.item.state,TVIS_BOLD
    mov insertTNode.item.stateMask,TVIS_OVERLAYMASK
    invoke SendMessage,hTreeWindow,TVM_INSERTITEM,0,addr insertTNode
    mov hRootNode,eax
  • 处理NOTIFY消息
  •   个人还是觉得重新写一个类继承TreeView,然后自己处理它的NOTIFY消息是最好的了.呵呵,常用的处理消息就是双击(NM_DBLCLK),正展开(TVN_ITEMEXPANDING)等等消息.这里说说NM_DBLCLK消息,收到这个消息时,肯定是在一个ITEM上发生了双击.想想QQ之类的程序,用户列表都是树型的,双击后就会触发事件,其实就是处理了这个消息.那么怎样得到双击的项目呢,这儿就必须通过HITTEST来取得这个ITEM了(TreeView_SelectItem这个宏应该就是用HITTEST实现的),HITTEST就是看当前鼠标是不是在某个ITEM上,上的话就返回这个ITEM的句柄.那么怎样通过句柄得到这个ITEM的其它属性呢?例如这个元素的文字?方法就是再次填充TVITEM的部分元素,然后通过TVM_GETITEM消息来取得它.TVM_GETITEM会读出TVITEM里的hItem,用它来找到指定元素,然后根据mask里指定的要读取的值,填入TVITEM.所以在发送TVM_GETITEM消息前要填充好mask和hItem!!!mask可以是TVIF_TEXT 等等.这里要非常注意!!!如果你要取得Text,你必须指定pszText指向一个缓冲空间(把pszText设为一个缓冲空间的首地址)和 cchTextMax.这是显然的,因为这个结构体里没有可放字符串的地方.下面这个代码处理了NM_DBLCLK消息:
    SelfNotify proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
      local TVI:TV_ITEM
      local TVHINFO:TV_HITTESTINFO
      local textBuf[50]:BYTE
      mov esi,lParam
      assume esi:ptr NMHDR
      .if [esi].code==NM_DBLCLK
        invoke GetCursorPos,addr TVHINFO.pt
        invoke ScreenToClient,hTreeWin,addr TVHINFO.pt
        mov TVHINFO.flags,TVHT_ONITEM or TVHT_ONITEMICON
        invoke SendMessage,hTreeWin,TVM_HITTEST,0,addr TVHINFO
        mov eax,TVHINFO.hItem
        .if eax==NULL || eax==hRootNode
        jmp @F
        .endif
        mov TVI.hItem,eax
        mov TVI.imask,TVIF_IMAGE or TVIF_SELECTEDIMAGE or TVIF_TEXT
        invoke GetStrAddr,addr textBuf
        mov TVI.pszText,eax
        mov TVI.cchTextMax,50
        invoke SendMessage,hTreeWin,TVM_GETITEM,0,addr TVI
        invoke MessageBox,NULL,TVI.pszText,addr textBuf,0
      .endif
      @@:
      invoke DefWindowProc,hWin,uMsg,wParam,lParam ;;;//注意这儿是必不可少的哦!!!!!
      ret
    SelfNotify endp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值