您的位置:首页 > 其它

TreeView 控件使用

2007-10-23 21:49 573 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: