diff --git a/Help/tslvclhelp.CHM b/Help/tslvclhelp.CHM index cbf1877..9a871e1 100644 Binary files a/Help/tslvclhelp.CHM and b/Help/tslvclhelp.CHM differ diff --git a/funcext/tvclib/utslvcltree.tsf b/funcext/tvclib/utslvcltree.tsf index bb5e901..69e5280 100644 --- a/funcext/tvclib/utslvcltree.tsf +++ b/funcext/tvclib/utslvcltree.tsf @@ -5,83 +5,598 @@ interface @date(20220510) **} uses utslvclauxiliary,utslvclbase,utslvclgdi; -type TVirtualListItem = class(tsluibase) + +type ttreelistwnd = class(TCustomScrollControl) {** - @ignore(忽略) %% - @explan(说明) list 的 item项目基类 + @explan(说明) tree控件窗口基类 %% **} - type THandleClass=class - end - function Create(List);override; + protected //滚动窗口相关 + function GetClientXCapacity();virtual; //宽度容量 begin - {** - @explan(说明) 构造函数%% - @param(list)(TVirtualList) item的所有者,必须是TVirtualList或者其派生 %% - **} - if(List is class(TVirtualList))then + r := integer(ClientRect[2]/GetXScrollDelta()); + return r; + end + function GetClientYCapacity();virtual; //高度容量 + begin + return integer(ClientRect[3]/GetYScrollDelta()); + end + function GetClientYCount();override; //高度项 + begin + return FItems.Count; + end + function GetClientXCount();override; //宽度间隔 + begin + return integer(FxClientMax/fColWidth); + end + function GetXScrollDelta();override; + begin + return FColWidth; + end + function GetYScrollDelta();override; + begin + return FItemHeight; + end + function PositionChanged();virtual; + begin + InvalidateRect(nil,false); + end + function UpDateScrollBar(); + begin + DoControlAlign(); + end + public //绘制相关 + function IncPaintLock(); + begin + BeginUpdate(); + end + function DecPaintLock(); + begin + EndUpdate(); + end + function DoEndUpDate();override; + begin + if not(IsUpDating())then begin - FOwner := List; + if FScroolChanged then + begin + FScroolChanged := false; + UpDateScrollBar(); + end end - hd := new THandleClass(); - try - FHandle := inttostr(int64(hd)); ////当前句柄唯一标识 - except - FHandle := inttostr(gettslvariableptr(hd)); - end; - inherited create(); - FWidth := 30; - end - function paint(cvs,x,y,xwidth,yheight);virtual; - begin - {** - @explan(说明) 绘制 %% - @param(cvs)(tcustomcanvas) canvas对象 %% - @param(x)(integer) 当前x轴位置 %% - @param(y)(integer) 当前y轴位置 %% - @param(xwidth)(integer) 最大项的宽度 %% - @param(yheight)(integer) 高度 %% - **} - end - property Width read FWidth write SetWidth; - property Handle read FHandle; - property Owner read FOwner; - {** - @param(width)(integer) 宽度 %% - @param(Owner)(TVirtualList) 所有者 %% - **} - function Recycling();override; - begin - FOwner := nil; inherited; end - private - FHandle; - function SetWidth(w);virtual; + function paint();override; begin - if w>0 and w <> FWidth then + xpos := GetXpos(); + ypos := GetYPos(); + // 计算需要重绘的区域 + ps := PAINTSTRUCT().rcPaint; + tp := ps[1]; + bo := ps[3]; + FirstLine := integer(max(0,yPos+(tp)/FItemHeight)); + LastLine := integer(min(ItemCount-1,yPos+(bo)/FItemHeight)); + FirstCol := integer(max(0,xPos+ps[0]/FColWidth)); + LastCol := integer(min(FColCount-1,xPos+ps[2]/FColWidth)); + x := FColWidth *(0-xPos); + cvs := Canvas; + cvs.Font := font; + PaintRect(cvs,yPos,FItemHeight,FirstLine,LastLine,xPos,FColWidth,FirstCol,LastCol); + end + function GetClientItemIndexs(); + begin + rc := ClientRect; + r := GetRectItemIndexs(rc); + return r[0]-> r[1]; + end + function doControlALign();override; + begin + if(IsUpDating())then begin - if Owner and(Owner.ItemMaxWidth=FWidth)or(Owner.ItemMaxWidth= 0 and IdxFItems.Count-1 then idx :=-1; + return idx; + end + Function GetItemByYPos(y); + begin + {** + @explan(说明) 通过y轴位置获得item %% + @param(y)(integer) y轴位置 %% + @return(TcustomTreeCtlNode) 项 %% + **} + idx := GetItemIndexByYpos(y); + if idx >= 0 then return FItems[idx]; + end + function GetItemIndex(item,guess); + begin + {** + @explan(说明) 获得item序号 %% + @param(item)(TcustomTreeCtlNode) item %% + @return(integer) 序号 %% + **} + for i :=(guess>0?guess:0) to FItems.Count-1 do + begin + if item=FItems[i] then return i; + end + return -1; + return FItems.Indexof(item); + end + function GetItemRect(item); + begin + {** + @explan(说明) 获得item区域 %% + @param(item)(TcustomTreeCtlNode) item %% + @return(array) array(左,上,右,下) %% + **} + idx := GetItemIndex(item); + if idx >= 0 then return GetItemRectByIndex(idx); + return array(); + end + function GetItemRectByIndex(idx); + begin + {** + @explan(说明) 通过id获得item区域 %% + @param(idx)(integer) 序号 %% + @return(array) array(左,上,右,下) %% + **} + if idx >= 0 and idx= 0 and idx= 0{ and idx})then return false; + Try + IncPaintLock(); + while idx <= ei do begin - Owner.ItemUpDated(true); + ei--; + if FItemMaxItemIndex>idx then FItemMaxItemIndex -= 1; + else if FItemMaxItemIndex=idx then FItemMaxItemIndex := nil; + it := FItems[idx]; + if it then reindex(FHashItems,array(it.Handle:nil)); + FItems.Deli(idx); + end + ItemUpDated(); + finally + DecPaintLock(); + end + end + function DeleteItemByIndex(idx); + begin + {** + @explan(说明) 删除位置的项 %% + @param(idx)(integer) 位置 %% + **} + if idx >= 0 and idxidx then FItemMaxItemIndex -= 1; + else if FItemMaxItemIndex=idx then FItemMaxItemIndex := nil; + it := FItems[idx]; + if it then reindex(FHashItems,array(it.Handle:nil)); + FItems.Deli(idx); + ItemUpDated(); + finally + DecPaintLock(); + end; + return true; + end + return false; + end + function InsertItems(its,idx);virtual; + begin + {** + @explan(说明) 在位置出入项 %% + @param(it)(array of TcustomTreeCtlNode) item %% + @param(idx)(integer) 位置 %% + **} + idx0 :=(idx >= 0 and idxFxClientMax then + begin + FItemMaxItemIndex := idx0; + FxClientMax := it.Width; + end else + begin + if FItemMaxItemIndex >= idx0 then FItemMaxItemIndex++; + end + FItems.InsertBefor(it,idx0); + idx0++; + FHashItems[it.handle]:= it; + end + end + ItemUpDated(); + finally + DecPaintLock(); + end; + end + function InsertItem(it,idx);virtual; + begin + {** + @explan(说明) 在位置出入项 %% + @param(it)(TcustomTreeCtlNode) item %% + @param(idx)(integer) 位置 %% + **} + //idx0 := FItems.Count; + try + IncPaintLock(); + idx0 :=(idx >= 0 and idxFxClientMax then + begin + FItemMaxItemIndex := idx0; + FxClientMax := it.Width; + end else + begin + if FItemMaxItemIndex >= idx0 then FItemMaxItemIndex++; + end + FItems.InsertBefor(it,idx0); + FHashItems[it.handle]:= it; + r := true; + end + end + ItemUpDated(); + finally + DecPaintLock(); + end; + return r; + end + + function AppendItem(v);virtual; + begin + {** + @explan(说明) 追加项 %% + @param(v)(TcustomTreeCtlNode) item %% + **} + return InsertItem(v,FItems.Count); + end + function AppendItems(vs);virtual; + begin + {** + @explan(说明) 批量追加项 %% + @param(v)(array of TcustomTreeCtlNode) 项集 %% + **} + id := FItems.count; + try + IncPaintLock(); + for i,v in vs do + begin + if v is class(TcustomTreeCtlNode)then + begin + if FHashItems[v.handle]then continue; + wd := v.width; + if not(FItemMaxItemIndex >= 0)then + begin + FxClientMax := CalcMaxItemWidth(); + owd := FxClientMax; + end + if FxClientMax= 0 and idx= 0 then + begin + rc := ClientRect; + yp := GetYPos(); + rc[1]:=(idx-yp)* FItemHeight; + rc[3]:= rc[1]+FItemHeight; + return rc; + end + end + private //属性变量 + FHashItems; + FItemHeight; //项高 + FColCount; //列数 + FColWidth; //列宽 + FScroolChanged; //滚动条修改 + FItemMinWidth; + FItemMaxItemIndex; + FItems; //项目 + FxClientMax; //水平宽度 + private //属性设置 + function ItemUpDated(); + begin + {** + @explan(说明) 更新状态 %% + @param(flag)(bool) 是否强制刷新,默认当项宽度不变的时候不刷新 %% + @param(idx)(integer) 更新id以后的序号 %% + **} + mx := CalcMaxItemWidth(); + IncPaintLock(); + if(FxClientMax <> mx)then + begin + FxClientMax := mx; + end + UpDateScrollBar(); + DecPaintLock(); + end + function GetRectItemIndexs(rc); + begin + yp := GetYPos(); + tp := rc[1]; + bo := rc[3]; + FirstLine := integer(tp/GetYScrollDelta())+yp; + LastLine := integer((bo)/GetYScrollDelta())+yp; + return array(FirstLine,LastLine); + end + function SetItemHeight(v); + begin + nv := ((v>0)?integer(v):0); + if FItemHeight <> nv then + begin + FItemHeight := nv; + UpDateScrollBar(); + end + end + function SetItemMinWidth(w); + begin + {** + @explan(说明) 设置最大宽度 + **} + if w>5 and FItemMinWidth <> w then + begin + FItemMinWidth := w; + if FItemMinWidth>FxClientMax then + begin + FxClientMax := FItemMinWidth; + end + end + end + function CalcMaxItemWidth(); + begin + {** + @explan(说明)计算最大的item宽度 %% + **} + mx := FItemMinWidth; + if ifnil(FItemMaxItemIndex)then + begin + FItemMaxItemIndex := 0; + for i := 0 to FItems.Count-1 do + begin + nwd := FItems[i].Width; + if nwd>mx then + begin + mx := nwd; + FItemMaxItemIndex := i; + end + end + end else + begin + return FxClientMax; + end + return mx; + end + function PrevPaint(begid,endid);virtual; + begin + end + function GetItemCount();override; + begin + return FItems.Count; + end + function GetItems(); + begin + r := array(); + for i := 0 to FItems.Count-1 do r[i]:= FItems[i]; + return r; + end + end -type TcustomTreeCtlNode = class(TVirtualListItem) +type TTreeSelCHngedEvent=class(tuieventbase) + {** + @explan(说明) 导航选择改变消息%% + **} + function create(m,w,l,h);override; + begin + inherited; + end + ItemOld; + ItemNew; + Item; + {** + @param(ItemOld)(TcustomTreeCtlNode) 旧的节点 %% + @param(ItemNew)(TcustomTreeCtlNode) 新节点 %% + @param(Item)(TcustomTreeCtlNode) 当前节点 %% + **} +end +type TcustomTreeCtlNode = class(tsluibase) //树结点 {** @explan(说明) 树结点 %% **} - protected - FItems; //子项 - FParent; //父节点 - private + + private //绘制信息 FBasePos;//周边基准位置 FCheckPos; //checkbox位置 FExpandPos; //展开按钮位置 @@ -166,7 +681,30 @@ type TcustomTreeCtlNode = class(TVirtualListItem) end return true; end - public + public //常用函数 + function Create(List);override; + begin + inherited create(); + initnodehandle(); + if(List is class(TcustomTreeCtl))then + begin + FOwner := List; + end + FWidth := 30; + FVisible := true; + FMouseCanChecked := true; + FModifyChildrenChecked := true; + FFocusColor := array(0xfaf0e6,0xfac000) ;//array(rgb(230,240,250),rgb(0,192,250)); + FCheckWidth := 16; + FExpandWidth := 12; + FBasePos := 10; + FHierarchyWidth := 20; + FItems := new TFpList(); //子项 + FHierarchy :=-1; + FEexpanded := false; + FChecked := false; + FExpandImgId :=-1; + end function Paint(cvs,x,y,w,h);override; //绘制 begin {** @@ -244,10 +782,8 @@ type TcustomTreeCtlNode = class(TVirtualListItem) begin cvs.Pen.Color := 0x969696; cvs.Pen.style := PS_DOT; - for i,v in ow.GetHierarchyByHandle(self.Handle) do + for i,v in ow.ExecuteCommand("gethierarchybyhandle",self.Handle) do begin - //FLG := TRUE; - //nx := cbase-FHierarchyWidth*(i+1)+6; nx := cbase+FHierarchyWidth *(i-FHierarchy-1)+6; if nx>cbase-5 then break; cvs.MoveTo(array(nx,y)); @@ -301,23 +837,7 @@ type TcustomTreeCtlNode = class(TVirtualListItem) end return false; end - function Create(AOwner);override; - begin - inherited; - FVisible := true; - FMouseCanChecked := true; - FModifyChildrenChecked := true; - FFocusColor := array(0xfaf0e6,0xfac000) ;//array(rgb(230,240,250),rgb(0,192,250)); - FCheckWidth := 16; - FExpandWidth := 12; - FBasePos := 10; - FHierarchyWidth := 20; - FItems := new TFpList(); //子项 - FHierarchy :=-1; - FEexpanded := false; - FChecked := false; - FExpandImgId :=-1; - end + function GetNodeByIndex(idx); begin {** @@ -595,13 +1115,14 @@ type TcustomTreeCtlNode = class(TVirtualListItem) {** @explan(说明) 展开节点 %% **} - if Owner and Owner.RootNode=self then return; + ow := Owner; + if ow and ow.RootNode=self then return; if FExpanded then return; if ItemCount<1 then //空节点展开 begin if FDirtype then begin - Owner.EmptyNodeExpanding(self(true)); + ow.ExecuteCommand("emptynodeexpanding",self(true)); end return; end @@ -682,6 +1203,7 @@ type TcustomTreeCtlNode = class(TVirtualListItem) it.Recycling(); end //if self<>Owner.RootNode then + FOwner := nil; inherited; end function GetShowItemCount(); @@ -767,9 +1289,18 @@ type TcustomTreeCtlNode = class(TVirtualListItem) @param(ModifyChildrenChecked)(bool) 勾选的时候是否修改自己的勾选状态 %% @param(MouseCanChecked)(bool) 能否使用鼠标点击勾选 %% **} - protected + property Width read FWidth write SetWidth; + property Handle read FHandle; + property Owner read FOwner; + {** + @param(width)(integer) 宽度 %% + @param(Owner)(TcustomTreeCtl) 所有者 %% + **} + protected //父子节点设置相关 property CurrentDeleteNode read FCurrentDeleteNode write FCurrentDeleteNode; property CurrentAddNode read FCurrentAddNode write FCurrentAddNode; + FItems; //子项 + FParent; //父节点 function Gitems(); begin return FItems; @@ -820,7 +1351,50 @@ type TcustomTreeCtlNode = class(TVirtualListItem) if ow then ow.InvalidateItem(self,false); end end - private + private //成员变量 + FHandle; + FWidth; + FOwner; + + FVisible; + FDirtype; + FImgId; + FMouseCanChecked; + FModifyChildrenChecked; + FSelImgId; + FCurrentDeleteNode; + FCurrentAddNode; + FExpanded; + FExpandImgId; + FHierarchy; //层级 + FCaption; //标题 + FChecked; //选择 + private //普通属性设置 + function initnodehandle(); + begin + hd := new THandleClass(); + try + FHandle := inttostr(int64(hd)); ////当前句柄唯一标识 + except + FHandle := inttostr(gettslvariableptr(hd)); + end; + end + function SetWidth(w);virtual; + begin + if w>0 and w <> FWidth then + begin + ow := Owner; + if ow and(ow.ItemMaxWidth=FWidth)or(ow.ItemMaxWidth FCaption then @@ -945,700 +1507,16 @@ type TcustomTreeCtlNode = class(TVirtualListItem) return FItems.Count; end end -type TVirtualListFixed = class(TCustomScrollControl) - {** - @ignore(忽略) %% - @explan(说明) 滚动条窗口 %% - **} - protected - function GetClientXCapacity();virtual; //宽度容量 - begin - r := integer(ClientRect[2]/GetXScrollDelta()); - return r; - end - function GetClientYCapacity();virtual; //高度容量 - begin - return integer(ClientRect[3]/GetYScrollDelta()); - end - function GetClientXCount();virtual; //宽度间隔 - begin - return ColCount; - end - function GetClientYCount();virtual; //高度项 - begin - return FItemCount; - end - function GetXScrollDelta();override; - begin - return FColWidth; - end - function GetYScrollDelta();override; - begin - return FItemHeight; - end - function PositionChanged();virtual; - begin - InvalidateRect(nil,false); - end - function UpDateScrollBar(); - begin - DoControlAlign(); - end - public - function IncPaintLock(); - begin - BeginUpdate(); - end - function DecPaintLock(); - begin - EndUpdate(); - end - function DoEndUpDate();override; - begin - if not(IsUpDating())then - begin - if FScroolChanged then - begin - FScroolChanged := false; - UpDateScrollBar(); - end - end - inherited; - end - function GetItemIndexByYpos(y);virtual; - begin - py := GetYPos(); - return integer(y/GetYScrollDelta())+py; - end - function ItemUpDated();virtual; - begin - //空函数 - UpDateScrollBar(); - end - function GetValidateRect();virtual; - begin - {** - @explan(说明) 获得绘制区域 %% - @return(array) array(左,上,右,下) %% - **} - return FValidateRect; - end - function Create(AOwner);override; - begin - inherited; - FItemHeight := 25; - FItemCount := 0; - height := 400; - width := 300; - FColWidth := 10; - FColCount := 0; - border := true; - autoscroll := 3; - ThumbTrack := true; - FScroolChanged := false; - end - function SetTopLine(v);virtual; - begin - SetYpos(v); - end - function paint();override; - begin - xpos := GetXpos(); - ypos := GetYPos(); - // 计算需要重绘的区域 - ps := PAINTSTRUCT().rcPaint; - tp := ps[1]; - bo := ps[3]; - FValidateRect := ps; - FirstLine := integer(max(0,yPos+(tp)/FItemHeight)); - LastLine := integer(min(ItemCount-1,yPos+(bo)/FItemHeight)); - FirstCol := integer(max(0,xPos+ps[0]/FColWidth)); - LastCol := integer(min(FColCount-1,xPos+ps[2]/FColWidth)); - x := FColWidth *(0-xPos); - cvs := Canvas; - cvs.Font := font; - PaintRect(cvs,yPos,FItemHeight,FirstLine,LastLine,xPos,FColWidth,FirstCol,LastCol); - FValidateRect := array(); - end - function PaintRect(cvs,yPos,ht,FirstLine,LastLine,xPos,wd,FirstCol,LastCol);virtual; - begin - {** - @explan(说明) 绘制无效区域 %% - **} - for i := FirstLine to LastLine do - begin - y := ht *(i-yPos)+FMarginTop; - for j := FirstCol to LastCol do - begin - x := wd *(j-xPos); - cvs.Textout(format("%d=%d",i,j),array(x,y)); - end - end - end - function Clean();virtual; - begin - {** - @explan(说明) 清空 %% - **} - ColCount := 0; - end - function GetIndexClientRect(idx);virtual; - begin - if idx >= 0 then - begin - rc := ClientRect; - yp := GetYPos(); - rc[1]:=(idx-yp)* FItemHeight; - rc[3]:= rc[1]+FItemHeight; - return rc; - end - end - function GetIndexRect(idx);virtual; - begin - {** - @explan(说明) 通过id获得item区域 %% - @param(idx)(integer) 序号 %% - @return(array) array(左,上,右,下) %% - **} - r := GetIndexClientRect(idx); - if r then - begin - r[0]:= FColWidth *(0-GetXpos()); - end - return r; - end - function GetClientItemIndexs();virtual; - begin - rc := ClientRect; - r := GetRectItemIndexs(rc); - return r[0]-> r[1]; - end - function doControlALign();override; - begin - if(IsUpDating())then - begin - FScroolChanged := true; - end else - begin - InitialScroll(); - end - end - property ItemCount read GetItemCount write SetItemCount; - property ItemHeight read FItemHeight write SetItemHeight; - property ColCount read FColCount write SetColCount; - property ColWidth read FColWidth write SetColWidth; - private - FValidateRect; - FItemCount; //项数量 - FItemHeight; //项高 - FColCount; //列数 - FColWidth; //列宽 - FScroolChanged; //滚动条修改 - function GetRectItemIndexs(rc); - begin - yp := GetYPos(); - tp := rc[1]; - bo := rc[3]; - FirstLine := integer(tp/GetYScrollDelta())+yp; - LastLine := integer((bo)/GetYScrollDelta())+yp; - return array(FirstLine,LastLine); - end - function SetColWidth(h); - begin - if FColWidth <> h and h>5 then - begin - FColWidth := h; - UpDateScrollBar(); - end - end - function SetColCount(v); - begin - nv := GZNumber(v); - if nv >= 0 and nv <> FColCount then - begin - FColCount := nv; - UpDateScrollBar(); - end - end - function GetItemCount();virtual; - begin - return FItemCount; - end - function SetItemCount(v);virtual; - begin - nv := GZNumber(v); - if nv >= 0 and nv <> FItemCount then - begin - FItemCount := nv; - UpDateScrollBar(); - end - end - function SetItemHeight(v); - begin - nv := GZNumber(v); - if FItemHeight <> nv then - begin - FItemHeight := nv; - UpDateScrollBar(); - end - end - function GZNumber(v); - begin - return v>0?integer(v):0; - end -end -type TVirtualList = class(TVirtualListFixed) - {** - @ignore(忽略) %% - @explan(说明) 虚拟的list - **} - function GetClientYCount();override; //高度项 - begin - return FItems.Count; - end - function GetClientXCount();override; //宽度间隔 - begin - return integer(FxClientMax/ColWidth); - end - function Create(AOwner);override; - begin - inherited; - FxClientMax := ColWidth; - FItemMinWidth := FxClientMax; - FHashItems := array(); - FItems := new TFpList(); - end - function GetItemByIndex(idx); - begin - {** - @explan(说明) 通过id获得序号 %% - @param(idx)(integer) 序号 %% - @return(TVirtualListItem) 项 %% - **} - if idx >= 0 and IdxFItems.Count-1 then idx :=-1; - return idx; - end - Function GetItemByYPos(y); - begin - {** - @explan(说明) 通过y轴位置获得item %% - @param(y)(integer) y轴位置 %% - @return(TVirtualListItem) 项 %% - **} - idx := GetItemIndexByYpos(y); - if idx >= 0 then return FItems[idx]; - end - function GetItemIndex(item,guess); - begin - {** - @explan(说明) 获得item序号 %% - @param(item)(TVirtualListItem) item %% - @return(integer) 序号 %% - **} - for i :=(guess>0?guess:0)to FItems.Count-1 do - begin - if item=FItems[i]then return i; - end - return -1; - return FItems.Indexof(item); - end - function GetItemRect(item); - begin - {** - @explan(说明) 获得item区域 %% - @param(item)(TVirtualListItem) item %% - @return(array) array(左,上,右,下) %% - **} - idx := GetItemIndex(item); - if idx >= 0 then return GetItemRectByIndex(idx); - return array(); - end - function GetItemRectByIndex(idx);virtual; - begin - {** - @explan(说明) 通过id获得item区域 %% - @param(idx)(integer) 序号 %% - @return(array) array(左,上,右,下) %% - **} - if idx >= 0 and idx= 0 and idx= 0 and idxFxClientMax then - begin - FItemMaxItemIndex := idx0; - FxClientMax := it.Width; - end else - begin - if FItemMaxItemIndex >= idx0 then FItemMaxItemIndex++; - end - FItems.InsertBefor(it,idx0); - idx0++; - FHashItems[it.handle]:= it; - end - end - ItemUpDated(); - finally - DecPaintLock(); - end; - end - function InsertItem(it,idx);virtual; - begin - {** - @explan(说明) 在位置出入项 %% - @param(it)(TVirtualListItem) item %% - @param(idx)(integer) 位置 %% - **} - //idx0 := FItems.Count; - try - IncPaintLock(); - idx0 :=(idx >= 0 and idxFxClientMax then - begin - FItemMaxItemIndex := idx0; - FxClientMax := it.Width; - end else - begin - if FItemMaxItemIndex >= idx0 then FItemMaxItemIndex++; - end - FItems.InsertBefor(it,idx0); - FHashItems[it.handle]:= it; - r := true; - end - end - ItemUpDated(); - finally - DecPaintLock(); - end; - return r; - end - function DeleteItemByBounds(b,e);virtual; - begin - idx := b; - ei := e; - if not(idx >= 0{ and idx})then return false; - Try - IncPaintLock(); - while idx <= ei do - begin - ei--; - if FItemMaxItemIndex>idx then FItemMaxItemIndex -= 1; - else if FItemMaxItemIndex=idx then FItemMaxItemIndex := nil; - it := FItems[idx]; - if it then reindex(FHashItems,array(it.Handle:nil)); - FItems.Deli(idx); - end - ItemUpDated(); - finally - DecPaintLock(); - end - end - function DeleteItemByIndex(idx);virtual; - begin - {** - @explan(说明) 删除位置的项 %% - @param(idx)(integer) 位置 %% - **} - if idx >= 0 and idxidx then FItemMaxItemIndex -= 1; - else if FItemMaxItemIndex=idx then FItemMaxItemIndex := nil; - it := FItems[idx]; - if it then reindex(FHashItems,array(it.Handle:nil)); - FItems.Deli(idx); - ItemUpDated(); - finally - DecPaintLock(); - end; - return true; - end - return false; - end - function AppendItem(v);virtual; - begin - {** - @explan(说明) 追加项 %% - @param(v)(TVirtualListItem) item %% - **} - return InsertItem(v,FItems.Count); - end - function AppendItems(vs);virtual; - begin - {** - @explan(说明) 批量追加项 %% - @param(v)(array of TVirtualListItem) 项集 %% - **} - id := FItems.count; - try - IncPaintLock(); - for i,v in vs do - begin - if v is class(TVirtualListItem)then - begin - if FHashItems[v.handle]then continue; - wd := v.width; - if not(FItemMaxItemIndex >= 0)then - begin - FxClientMax := CalcMaxItemWidth(); - owd := FxClientMax; - end - if FxClientMax mx)then - begin - FxClientMax := mx; - end - UpDateScrollBar(); - DecPaintLock(); - end - function PaintRect(cvs,yPos,ht,FirstLine,LastLine,xPos,wd,FirstCol,LastCol);override; - begin - x := wd *(0-xPos); - rc := ClientRect; - PrevPaint(FirstLine,LastLine); - for i := FirstLine to LastLine do - begin - nrc := GetIndexRect(i); - //ri GetItemRectByIndex(i); - it := FItems[i]; - //y := ht * (i - yPos)+100; - it.paint(cvs,x,nrc[1],rc[2]-rc[1]-x,ht); - end - end - function SetTopLine(idx);override; - begin - {** - @explan(说明) 将idx行放入client区域 %% - @param(idx)(integer) 行号 %% - **} - if idx >= 0 and idx5 and FItemMinWidth <> w then - begin - FItemMinWidth := w; - if FItemMinWidth>FxClientMax then - begin - FxClientMax := FItemMinWidth; - ColCount := integer(FxClientMax/ColWidth+0.5); - end - end - end - function CalcMaxItemWidth();virtual; - begin - {** - @explan(说明)计算最大的item宽度 %% - **} - mx := FItemMinWidth; - if ifnil(FItemMaxItemIndex)then - begin - FItemMaxItemIndex := 0; - for i := 0 to FItems.Count-1 do - begin - nwd := FItems[i].Width; - if nwd>mx then - begin - mx := nwd; - FItemMaxItemIndex := i; - end - end - end else - begin - return FxClientMax; - end - return mx; - end - - private - FHashItems; - function PrevPaint(begid,endid);virtual; - begin - end - function GetItemCount();override; - begin - return FItems.Count; - end - function SetColWidth();override; - begin - end - function SetItemCount();override; - begin - end - function GetItems(); - begin - r := array(); - for i := 0 to FItems.Count-1 do r[i]:= FItems[i]; - return r; - end - FItemMinWidth; - FItemMaxItemIndex; - FItems; //项目 - FxClientMax; //水平宽度 -end -type TcustomTreeCtl = class(TVirtualList) +type TcustomTreeCtl = class(ttreelistwnd) {** @explan(说明) 树控件 %% **} - type TTreeSelCHngedEvent=class(tuieventbase) - {** - @explan(说明) 导航选择改变消息%% - **} - function create(m,w,l,h);override; - begin - inherited; - end - ItemOld; - ItemNew; - Item; - end + public //常用 function Create(AOwner);override; + begin + inherited; + end + function AfterConstruction();override; begin inherited; fcountlocker := new tcountkernel(); @@ -1649,7 +1527,34 @@ type TcustomTreeCtl = class(TVirtualList) FMulSelected := false; FMulSelects := array(); fnodecreator := class(TcustomTreeCtlNode); - end + end + function ExecuteCommand(cmd,pm);override; + begin + case cmd of + "gethierarchybyhandle": + begin + if FPaintArray then return FPaintArray[pm]; + return 0; + end + "emptynodeexpanding": + begin + if HandleAllocated()then + begin + if FonEmptyNodeExapanding then + begin + e := new TTreeSelCHngedEvent(0,0,0,0); + e.item := item; + e.ItemNew := item; + e.ItemOld := item; + calldatafunction(FonEmptyNodeExapanding,pm,e); + end + end + return ; + end + + end + return inherited; + end function InsertItem(it,idx);override; begin if it is class(TcustomTreeCtlNode)then return inherited; @@ -1662,42 +1567,13 @@ type TcustomTreeCtl = class(TVirtualList) for i,it in its do if it is class(TcustomTreeCtlNode)then lst[lsti++]:= it; inherited InsertItems(lst,idx); end - function WMKEYUP(o,e);override; - begin - if not FCurrentNode then return; - if e.skip then return ; - case e.charcode of - VK_UP,VK_DOWN: - begin - id := GetItemIndex(FCurrentNode); - setsel(GetItemByIndex((VK_UP=e.charcode)?(id-1):(id+1))); - end - VK_LEFT: - begin - if FCurrentNode.Expanded then - begin - FCurrentNode.UnExpand() - end - else - begin - p := FCurrentNode.Parent; - if RootNode=p then return ; - SetSel(p); - end - end - VK_RIGHT: - begin - FCurrentNode.Expand(); - end - end; - end function hasFocus();virtual; begin return true; - end + end function AppendItem(it);override; begin - if it is class(TcustomTreeCtlNode)then return inherited; + if it is class(TcustomTreeCtlNode) then return inherited; return false; end function SetSel(it);virtual; @@ -1772,12 +1648,6 @@ type TcustomTreeCtl = class(TVirtualList) function CreateTreeNode();virtual; begin return createobject(fnodecreator,self(true)); - r := new TcustomTreeCtlNode(self(true)); - return r; - end - function DeleteNode(nd);virtual; - begin - if FRootItem then FRootItem.DeleteNode(nd); end function NodeInList(it); begin @@ -1787,6 +1657,10 @@ type TcustomTreeCtl = class(TVirtualList) if it=FRootItem then return FRootItem; return ItemInList(it); end + function DeleteNode(nd);virtual; + begin + if FRootItem then FRootItem.DeleteNode(nd); + end function MouseDown(o,e);override; begin if e.shiftdouble()and e.button()=mbLeft then //双击 @@ -1828,6 +1702,43 @@ type TcustomTreeCtl = class(TVirtualList) end //e.skip := true; end + function WMKEYUP(o,e);override; + begin + if not FCurrentNode then return; + if e.skip then return ; + case e.charcode of + VK_UP,VK_DOWN: + begin + id := GetItemIndex(FCurrentNode); + setsel(GetItemByIndex((VK_UP=e.charcode)?(id-1):(id+1))); + end + VK_LEFT: + begin + if FCurrentNode.Expanded then + begin + FCurrentNode.UnExpand() + end + else + begin + p := FCurrentNode.Parent; + if RootNode=p then return ; + SetSel(p); + end + end + VK_RIGHT: + begin + FCurrentNode.Expand(); + end + end; + end + function Clean();override; + begin + if FRootItem then + begin + lk := new tcountlocker(fcountlocker); + FRootItem.DeleteChildren(); + end + end function Recycling();override; begin lk := new tcountlocker(fcountlocker); @@ -1839,32 +1750,7 @@ type TcustomTreeCtl = class(TVirtualList) //fnodecreator := nil; inherited; end - function GetHierarchyByHandle(h); - begin - if FPaintArray then return FPaintArray[h]; - end - function EmptyNodeExpanding(item); - begin - if HandleAllocated()then - begin - if FonEmptyNodeExapanding then - begin - e := new TTreeSelCHngedEvent(self.Handle,0,0,0); - e.item := item; - e.ItemNew := item; - e.ItemOld := item; - calldatafunction(FonEmptyNodeExapanding,self(true),e); - end - end - end - function Clean();override; - begin - if FRootItem then - begin - lk := new tcountlocker(fcountlocker); - FRootItem.DeleteChildren(); - end - end + published //属性 property CurrentNode read FCurrentNode write setcurrentnode; //20221118 加上写 property CheckBox:bool read FCheckBox write SetCheckBox; property HasLine:bool read FHasLine write SetHasLine; @@ -1877,7 +1763,7 @@ type TcustomTreeCtl = class(TVirtualList) property OnSelChanging:eventhandler read FOnSelChanging write FOnSelChanging; property onEmptyNodeExapanding read FonEmptyNodeExapanding write FonEmptyNodeExapanding; property nodecreator read fnodecreator write setnodecreator; - protected + protected //子类可以用的函数 function GetRootNode();virtual; //获得根节点 begin if not(FRootItem)or(ifobj(FRootItem)and(FRootItem.ReCycleState <> 0))then @@ -1887,13 +1773,24 @@ type TcustomTreeCtl = class(TVirtualList) //echo FRootItem.Owner,"\r\n"; return FRootItem; end - private + private //成员变量 fcountlocker; //锁定changed回调 fnodecreator; FOnlyLeafNodeCheckMark; FNodeHierarchyWidth; FMulSelected; FMulSelects; + FOnSelChanging; + FonEmptyNodeExapanding; + FSingleExpand; + FBKItemHeight; + FOnSelChanged; + FCurrentNode; + FRootItem; + FCheckBox; + FHasLine; + FPaintArray; + private //成员方法 function setcurrentnode(nd); begin setsel(nd); @@ -1924,7 +1821,7 @@ type TcustomTreeCtl = class(TVirtualList) t1 := FCurrentNode; //if t1 then InvalidateItem(t1,false); //InvalidateItem(it,false); - ne := new TTreeSelCHngedEvent(self.Handle,1,1,1); + ne := new TTreeSelCHngedEvent(0,0,0,0); ne.ItemOld := t1; ne.ItemNew := it; ne.Item := it; @@ -1935,16 +1832,6 @@ type TcustomTreeCtl = class(TVirtualList) end return r; end - FOnSelChanging; - FonEmptyNodeExapanding; - FSingleExpand; - FBKItemHeight; - FOnSelChanged; - FCurrentNode; - FRootItem; - FCheckBox; - FHasLine; - FPaintArray; function PrevPaint(begid,endid);virtual; begin if not FHasLine then return; @@ -2007,6 +1894,8 @@ type TcustomTreeCtl = class(TVirtualList) end implementation +type THandleClass=class()//句柄对象 +end initialization