unit utslvclcoolbar; {** @explan(说明) coolbar库,提供coolbar 支持 **} interface uses utslvclauxiliary,utslvclgdi; type tcustomcoolbar=class(tcustomcontrol) {** @explan(说明) coolbar基类 **} function Create(AOwner); begin fcoolbands := new tcoolbarlines(); fbtnwidth := 20; fdoaligncount :=0; inherited; end function AfterConstruction();override; begin inherited; Align := alTop; FWill_Drag := true; cimgst(); fdragbtncolor := _wapi.GetSysColor(COLOR_MENUBAR); end function ControlAppended(AControl);override; begin if fcoolbands then begin it := new tcoolband(AControl); fcoolbands.appendrow(it); end end function ControlDeleted(AControl);override; begin if fcoolbands then begin fcoolbands.deleteitem(AControl,true); end end function Notification(o,op);override; begin return inherited; if fsizelocker then return ; if (o is class(TWinControl)) and o.WsPopUp then return ; if HandleAllocated() and ifarray(op) and (op["type"]="possize") then //位置大小发送变化 begin ctls := controls; if (ctls.IndexOf(o)>=0) then //子控件大小变化 begin doControlALign();//InvalidateRect(nil,false); return ; end end inherited; end function WMLBUTTONUP(o,e);override;//拖拽实现 begin if csDesigning in ComponentState then exit; if FIs_Draging then begin _wapi.ImageList_DragLeave(self.Handle); _wapi.ImageList_EndDrag(); if fdragenode then begin r := fcoolbands.getnodebyxy(e.xpos,e.ypos); if fcoolbands.moveitemto(fdragenode,r[0],r[1]) then begin doControlALign(); InvalidateRect(nil,false); end end else if fsizenode then begin ctl := fsizenode.fctl; clr := ctl.BoundsRect; y := e.ypos; if y> clr[1] and (y10 then begin ctl.Width := nwid; doControlALign(); InvalidateRect(nil,false); end end end EnabledChild(true); FWill_Drag := true; FIs_Draging := false; _wapi.clipcursor(0); return ; end inherited; end function WMLButtonDown(o,e);override;//拖拽释放 begin if csDesigning in ComponentState then exit; xy := e.pos; trk := -1; for i,v in fcoolbands.data do begin if pointinrect(xy,v.fdragrect) then //拖拽 begin trk := 0; fdragenode := v; fsizenode := nil; break; end if pointinrect(xy,v.fsizerect) then //调整大小 begin trk := 1; fdragenode := nil; fsizenode := v; break; end end if trk<0 then return inherited; nxy := clienttowindow(e.xpos,e.ypos); if FWill_Drag then begin FWill_Drag := false; FIs_Draging := true; _wapi.ImageList_BeginDrag(FDRageimglist.Handle,trk,12,12); _wapi.ImageList_DragEnter(self.Handle,nxy[0],nxy[1]); crect := clientrect; ps := array(clienttoscreen(crect[0],crect[1]),clienttoscreen(crect[2],crect[3])); _wapi.clipcursor(ps); EnabledChild(false); return ; end inherited; end function WMMouseMove(o,e);override; //移动 begin if FIs_Draging then begin nxy := clienttowindow(e.xpos,e.ypos); _wapi.ImageList_DragMove(nxy[0],nxy[1]); return ; end else begin xy := e.pos(); for i,v in fcoolbands.data do begin if pointinrect(xy,v.fdragrect) then //拖拽 begin cursor := OCR_SIZEALL; flg := true; break; end if pointinrect(xy,v.fsizerect) then //拖拽 begin cursor := OCR_SIZEWE; flg := true; break; end end if flg then begin return ; end else begin cursor := OCR_NORMAL; end end inherited; end function GetPreferredSize(w,h);override; begin if fcoolbands then h := sum( fcoolbands.getrowheights()); else h := Height; w := Width; end function AdjustSize();override; begin inherited; doControlALign(); InvalidateRect(nil,false); end function doControlALign();override;//调整位置 begin if not HandleAllocated() then return ; //InvalidateRect(nil,false); mwid := 10; swid := 10; y := 0; rhs := fcoolbands.getrowheights(); {bal := Align; if fdoaligncount<50 and autosize and ( bal =alTop or bal=alBottom) then begin rc := ClientRect; nh := sum(rhs); h := rc[3]-rc[1]; bw := Height-h; dh := h-nh; if abs(dh)>4 then begin Align := alNone; Height := bw+nh; Align := bal; fdoaligncount++; return ; end end } fdoaligncount := 0; fsizelocker := true; for i,v in fcoolbands.data2 do begin x := 0; bss := array(); for j,bsi in v do begin ctl := bsi.fctl; if ctl.Visible and not((ctl is class(TWinControl)) and ctl.WsPopUp) then begin bss[length(bss)]:= bsi; drc := array(x,y+1,x+mwid,y+rhs[i]-2); bsi.fdragrect := drc; bsi.fbtnrect := drc; h := ctl.Height; w := ctl.Width; x += mwid; bsi.fctlrect := array(x,y+1,w,h); dy := 0; if (rhs[i]-h)>2 then begin dy := integer((rhs[i]-h)/2); end ctl.SetBounds(x,y+dy+1,w,h); x+=w; bsi.fsizerect := array(x,y+1,x+swid,y+rhs[i]-2); //x+=swid; end else begin bsi.fdragrect := array();//array(0,0,0,0); bsi.fctlrect := array();//array(0,0,0,0); bsi.fsizerect := array();//array(0,0,0,0); end end bsi.fsizerect := array();//array(0,0,0,0); y+=rhs[i]; for i := 0 to length(bss)-2 do //重新设置位置 begin bs := bss[i]; rc := bs.fsizerect; if rc then begin bs2 := bss[i+1]; rc[1] := rc[1]+integer((rc[3]-rc[1])/2); bs.fsizerect := rc; rc := bs2.fdragrect; rc[3] := rc[3]-integer((rc[3]-rc[1])/2); bs2.fdragrect := rc; end end end fsizelocker := false; end function paint();override; //绘制 begin dc := canvas; cl := dc.brush.color; bcl := dc.pen.color; dc.pen.color := 0xDCDCDC; rhs := fcoolbands.getrowheights(); y := 0; for i:= 0 to length(rhs)-2 do begin y +=rhs[i]; dc.moveto(array(0,y)); dc.lineto(array(width,y)); end for i,v in fcoolbands.data do begin dc.brush.color := fdragbtncolor; brc := v.fbtnrect; if brc then paintbtn(brc); end dc.brush.color := cl; dc.pen.color := bcl; end function Recycling();override; begin fcoolbands := nil; inherited; FDRageimglist := nil; end published property arrange:lazystr read getarrange write setarrange; property dragbtncolor:color read fdragbtncolor write fdragbtncolor; private fdoaligncount; fdragbtncolor; fsizelocker; function paintbtn(rc1); begin dc := canvas; rc1[0]+=1; rc1[1]+=1; rc1[2]-=1; rc1[3]-=1; dc.fillrect(rc1); ply := array( rc1[array(0,1)], rc1[array(2,1)], rc1[array(2,3)], rc1[array(0,3)], rc1[array(0,1)] ); dc.draw("polyline",ply) ; x := integer(rc1[0]+(rc1[2]-rc1[0])/2); y := integer(rc1[1]+(rc1[3]-rc1[1])/2); for i := -2 to 1 do begin y1 := y+i*4; if y1>rc1[1] and y1(ct); ncoollines := new tnumindexarray(); for i,v in str2array(ar,";") do begin if v then begin line := new tnumindexarray(); for j,vj in str2array(v,",") do begin idx := strtointdef(vj,-1); if idx>=0 then begin vidx := idxs[idx]; if vidx>=0 then begin reindex(idxs,array(idx:nil)); line.Push(new tcoolband(ctls[vidx])); end end end if line.length() then begin ncoollines.Push(line); end end end for i,v in idxs do begin line := new tnumindexarray(); line.Push(new tcoolband(ctls[v])); ncoollines.Push(line); end nb := new tcoolbarlines(); nb.lines := ncoollines; if getarrange()=getarrange(nb) then return ; //相同 fcoolbands := nb; if HandleAllocated() then begin doControlALign(); end end function EnabledChild(f); begin fcoolbands.EnabledChild(f); end function cimgst(); begin FDRageimglist := new TCustomImageList(self); FDRageimglist.Width := 24; FDRageimglist.Height := 24; bmp := new TcustomBitmap(); bmp.readvcon(HexFormatStrToTsl(getmovebmp())); FDRageimglist.addbmp(bmp); bmp := new TcustomBitmap(); bmp.readvcon(HexFormatStrToTsl(getsizebmp())); FDRageimglist.addbmp(bmp); end fdragenode; //拖拽的节点 fsizenode; //调整大小节点 fcoolbands; //节点管理器 fbtnwidth; FIs_Draging;// FWill_Drag;// FDRageimglist;// end implementation type tcoolband = class() //管理节点 function create(ctl); begin fctl := ctl; end function destroy(); begin end function enabled(f); begin if not f then begin if fenable<>nil then return ; fenable := fctl.Enabled; fctl.Enabled := false; end else begin fctl.Enabled := fenable; fenable := nil; end end function operator[](idx); begin try return invoke(fctl,idx); except return 0; end end [weakref]fctl; fdragrect; fsizerect; fctlrect; fbtnrect; private fenable; end type tcoolbarlines = class() //节点管理器 function create(); begin flines := new tnumindexarray(); end function appendrow(cb); //追加一行 begin line := new tnumindexarray(); line.Push(cb); flines.Push(line); end function unshiftrow(cb); //在前面 begin line := new tnumindexarray(); flines.unshift(line); end function deleteitem(it,ifctl); //删除一项 begin for i,v in flines.data do begin for j ,vj in v.data do begin if ifctl then vjctl := vj.fctl; else vjctl := vj; if vjctl = it then begin v.splice(j,1); if v.length()<1 then begin flines.splice(i,1);//删除 return 2; end return 1; end end end return 0; end function moveitemto(it,nit,f);//移动到坐标 begin if it=nit then return 0; bkr := 0; for i,v in data2 do //查找行列位置 begin for j,vj in v do begin if vj=it then begin id1 := array(i,j); end else if nit = vj then begin id2 := array(i,j); end if id1 and id2 then begin bkr := 1; break; end end if bkr then break; end if not(bkr) then return 0; if id1[0]=id2[0] then //同一行 begin if ((id1[1]-id2[1])=1) and f=3 then //在后面情况 begin return 0; end if ((id1[1]-id2[1])=-1) and (f=0 or f=1) then //在前面情况 begin return 0; end end deleteitem(it);//删掉 case f of 0,1,3: //前 begin ifg := f=3; end 2: //前一行 begin line := new tnumindexarray(); line.push(it); flines.unshift(line); return 1; end 4: //后一行 begin line := new tnumindexarray(); line.push(it); flines.Push(line); return 1; end end for i,v in flines.data do begin for j ,vj in v.data do begin if vj = nit then begin if ifg then //后面 begin v.splice(j+1,0,it); return 1; end else begin v.splice(j,0,it); return 1; end end end end return true; end function getrowheights(); //总高度 begin r := array(25); //默认高度 for i,v in getdata2() do begin h := 0; for j,vj in v do begin if vj["visible"] and not(vj["wspopup"]) then begin h := max(h,vj["height"]); end end r[i] := h+2;// max(20,h); end if (csDesigning in ComponentState) and (length(r)=1 and r[0]<2) then begin r[0] := max(25,r[0]); end return r; end function EnabledChild(f); //enable begin for i,v in flines.data do begin for j,vj in v.data do begin vj.enabled(f); end end end function getnodebyxy(x,y); //通过位置获得节点的信息,拖拽处理使用 begin rs := getrowheights(); b := 0; bdr := 3; rl := length(rs)-1; for i,v in rs do begin if v<1 then continue; if (y>=b and y<=b+v) or (i=0 and y=(rc[0])) and ( x<=(rc[0]+rc[2])) and (y>=(rc[1]+bdr)) and ( y<=(rc[1]+rc[3]-bdr)) then //中间位置 begin rt := 0; end if x<(rc[0]+bdr) then //左边 begin rt := 1; end if i=0 then begin if y<(rc[1]+bdr) then //上边 begin rt := 2; end end if i=rl then begin if y>(rc[1]+rc[3]-bdr) then //下边 begin rt := 4; end end if rt>-1 then return array(bsi,rt,i,j); //后边 end return array(bsi,3,i,j); end b+=v; end ri := length(rs)-1; return array((flines[ri])[0],4,ri,0); //字后面 end property data2 read getdata2; property data read getdata; property lines read flines write flines; private function getdata(); begin r := array(); k := 0; for i,v in flines.data do begin for j,vj in v.data do begin r[k] := vj; k++; end end return r; end function getdata2(); begin r := array(); k := 0; for i,v in flines.data do begin for j,vj in v.data do begin r[i,j] := vj; end end return r; end flines; end function getmovebmp(); //移动图片 begin return "0502000000060400000074797065000203000000696D670006040000006461746 10002E801000089504E470D0A1A0A0000000D4948445200000018000000180806 000000E0773DF8000000017352474200AECE1CE90000000467414D410000B18F0 BFC6105000000097048597300000EC300000EC301C76FA8640000017D49444154 484BB594BF2F044114C7FD1DFE06FF8446F41285CE3FA0D048682FA1500912AD6 8509C50A1D128885CA1398DECE5E2E2ECB27B2EB72C479E7C9F9D313BB3676692 BB4FF2B29BF9F13EB3F366678C468C97E0F4F68DC30767C1D6D92B4D2CB538F0E E8A93404DEE2BB10AB6CFBB4672112E12AB6061F785932DEEC585C478A2CF8655 9066DFB2B042707D9FD1453DE33E1BCE4506AAC01543803DAF54138A7BE6EA663 7421694B17290F057E91404EA69F159A53A4FFF4FA4403D2D28A8CE65FA4ED38D 36CD349F683DEAE4AD7F88AFD3252CA8DEA4B2538FF99D671E88C4E3774D8EC9E 0911A519FE636A3D239885AF0C1F358707835588095015DF0107F958E1771524B 799EDCA2E5FD4476624F5103442F3F8A83B6488C53B758FD010B455E3DEEC841F 5D667DE6A47DD62353928088038A661D7EF984EADB58DE4C010FC87586510F6F3 163B5641D95501D03694ABA2ECB2AB1CFD1E88A15C7623BFAE0112E9C92176C1B 9C8AAC465E50267014061F5CBCC8697C01FA21F97353FCB2FCC13D10000000049 454E44AE42608200"; end function getsizebmp(); //调整大小图片 begin return "0502000000060400000074797065000203000000696D670006040000006461746 100020E01000089504E470D0A1A0A0000000D4948445200000018000000180806 000000E0773DF8000000017352474200AECE1CE90000000467414D410000B18F0 BFC6105000000097048597300000EC300000EC301C76FA864000000A349444154 484BED93BB0E84300C04F3E7499B3675DA7C674E8B6CB45C1E46C09D0462240A6 CD603065CFD31AFC0E4E1821042F5DECB598BD5074301C2CEB9E5E80DB1FA4A57 808086638C526D41CF9234021E9E5292EA185C33936C04FCD83967A9DAE0DA916 415F0F0528A54F7834C4FB20A78356705B85965B322961C5D110F07FF7DC90A4B 2EFF4C15EB47E2FEF75A98A10020380B5B7D30155CC12B30B9BBA0D60F44173C9 EBDFC87F10000000049454E44AE42608200"; end initialization end.