原贴位置:http://www.hur.cn/bbs/dispbbs.asp?boardid=85&id=60818
树在程序中应用很广泛,很多新手对创建树总是感到很难。这里举一个树的应用例程(该例程在我原来提供的一个树的控件基础上,增加2个函数实现)。当然,如果大家要做3态、4态的checkbox,在我的程序基础上稍微动动脑筋就能实现。如图:
[upload=jpg]UploadFile/2007-7/200771521302926660.jpg[/upload]
需要达到的目标:
1、选中或取消选中一个节点(checkboxes状态改变)时,树能历遍该节点下的所有子节点,使子节点的状态和当前节点状态一致。
2、能方便的取得已经选中的状态。
问题难点:
1、点击标签(即显示的文字),节点状态不能改变,否则展开树的时候有问题。
2、pb没有提供树节点状态改变的事件,所以只能写在clicked事件里面,当用户点击标签时,立即触发clicked事件,这和第一条矛盾。
3、综合以上2点:我们必须要在clicked事件中,点击checkboxes时,才可以触发改变状态的程序
4、节点是否选中、或者如何通过程序选中节点,这个问题困扰了我很长时间,最后发现pb是通过设置或判断statepictrue来处理checkboxs的。
5、clicked事件里面,一直要等到代码全部执行好之后,才改变节点状态
废话不多说。
首先解决1、2、3、4点难题:
需要借助api来判断是否点击了checkboxes。
申明API:Function integer getiteminfo(long hWnd, long uMsg, long wParam, REF TVHITTESTINFO tv) library "user32.dll" Alias For "SendMessageA"
该API所需要的结构在程序中已经创建,大家可以自己看。
定义一个事件mousemove(pbm_mousemove),然后在mousemove事件里面写如下代码:
//====================================================================
// 得到节点状态
//====================================================================
tvhittestinfo ltvitem
tvitem Item
long ll_handle
RECT ItemRect, WindowRect
POINT point
ll_handle = handle(this)
ltvitem.pt.xx = UnitsToPixels (xpos, XUnitsToPixels! )
ltvitem.pt.yy = UnitsToPixels (ypos, YUnitsToPixels! )
getiteminfo(handle(this),4369,0,ltvitem)
IF ltvitem.hItem = 0 then return
ib_ischeckboxes = (ltvitem.flags = 64 )
//====================================================================
// 说明:ib_ischeckboxes 是树的instance variables。true :光标下是checkboxes
//====================================================================
然后定义2个函数:
//====================================================================
// 函数: vu_treeview::of_select()
//--------------------------------------------------------------------
// 描述: 通过设置状态图标,设置是否选中
//--------------------------------------------------------------------
// 参数:
// value long al_handle 节点句柄
// value integer ai_picid 状态图片序号
//--------------------------------------------------------------------
// 返回: (none)
//--------------------------------------------------------------------
// 作者: 程宁 日期: 2007.07.15
//--------------------------------------------------------------------
// 修改历史:
//
//====================================================================
TreeViewItem ltvi_item
this.GetItem(al_handle, ltvi_item)
ltvi_item.statepictureindex = ai_picid
setitem( al_handle , ltvi_item )
//====================================================================
// 函数: vu_treeview::of_isselect()
//--------------------------------------------------------------------
// 描述: 判断某个节点是否被选中(在有checkboxs的状态下)
//--------------------------------------------------------------------
// 参数:
// value long al_handle 节点句柄
// value integer ai_selectpicid 选中的图片号
//--------------------------------------------------------------------
// 返回: boolean
//--------------------------------------------------------------------
// 作者: 程宁 日期: 2007.07.15
//--------------------------------------------------------------------
// 修改历史:
//
//====================================================================
TreeViewItem ltvi_item
this.GetItem(al_handle, ltvi_item)
return ltvi_item.statepictureindex = ai_selectpicid
然后,在树的clicked里面写一段代码,注意程序里面有很长一段注释,主要解决第五个难点,大家可以把相应代码注释掉,然后运行看看效果:
if this.ib_ischeckboxes then
//首先判断是不是点击了选择框
ib_select = this.of_isselect( handle , 1 )
this.of_scanallitem( handle , 'selectitem')
/*重要:
以原来状态是未选中为例解释:
原来的状态1
前面的一句of_scanallitem,将节点状态置成2
clicked事件完成之后,节点状态会被重新置成1,与目标不符
故,下面的代码是将节点状态置成of_scanallitem之前的原始状态,
保证clicked事件之后,图片能显示成正确的状态
不知道我这样写大家能否理解^_^*/
if ib_select then
this.of_select( handle , 1 )
else
this.of_select( handle , 2 )
end if
end if
历遍改变节点状态主要是通过of_scanallitem( handle , 'selectitem')函数以及tree的ue_expfun来实现的。我在之前的帖子中有说明,这里不多说。
ue_expfun事件代码:
string ls_data,ls_label
choose case as_evename
case 'selectitem'
//设置节点是否选中
if ib_select then
this.of_select( al_handle , 2 )
else
this.of_select( al_handle , 1 )
end if
case 'getselect'
//得到选中的节点
if tv_2.of_isselect( al_handle , 2 ) then
tv_2.of_getdata( al_handle , ls_data , ls_label )
is_selectitem += "data:"+ls_data+"~tlabel:"+ls_label + '~r~n'
end if
end choose