730 lines
21 KiB
Plaintext
730 lines
21 KiB
Plaintext
unit utslvclcoolbar;
|
|
{**
|
|
@explan(说明) coolbar库,提供coolbar 支持
|
|
**}
|
|
interface
|
|
uses utslvclauxiliary,utslvclgdi;
|
|
type tcustomcoolbar=class(tcustomcontrol)
|
|
{**
|
|
@explan(说明) coolbar基类
|
|
**}
|
|
function Create(AOwner);
|
|
begin
|
|
fcoolbands := new tcoolbarlines();
|
|
fbtnwidth := 20;
|
|
fautosize := true;
|
|
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
|
|
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 (y<clr[1]+clr[3]) then
|
|
begin
|
|
nwid := e.xpos-ctl.left;
|
|
if nwid>10 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 doControlALign();override;//调整位置
|
|
begin
|
|
if not HandleAllocated() then return ;
|
|
mwid := 10;
|
|
swid := 10;
|
|
y := 0;
|
|
rhs := fcoolbands.getrowheights();
|
|
bal := Align;
|
|
if fdoaligncount<5 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,x+mwid,y+rhs[i]);
|
|
bsi.fdragrect := drc;
|
|
bsi.fbtnrect := drc;
|
|
h := ctl.Height;
|
|
w := ctl.Width;
|
|
x += mwid;
|
|
bsi.fctlrect := array(x,y,w,h);
|
|
dy := 0;
|
|
if (rhs[i]-h)>2 then
|
|
begin
|
|
dy := integer((rhs[i]-h)/2);
|
|
end
|
|
ctl.SetBounds(x,y+dy,w,h);
|
|
x+=w;
|
|
bsi.fsizerect := array(x,y,x+swid,y+rhs[i]);
|
|
//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 autosize:bool read fautosize write setautosize;
|
|
property arrange:lazystr read getarrange write setarrange;
|
|
property dragbtncolor:color read fdragbtncolor write fdragbtncolor;
|
|
private
|
|
fdoaligncount;
|
|
fautosize ;
|
|
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<rc1[3] then
|
|
dc.SetPixel(array(x,y1),30);
|
|
end
|
|
end
|
|
function arange2a(s);
|
|
begin
|
|
ss := str2array(s,";");
|
|
rs := array();
|
|
for i,v in ss do
|
|
begin
|
|
if trim(v) then
|
|
begin
|
|
str2array(v,",");
|
|
end
|
|
end
|
|
|
|
end
|
|
function getarrange(b);
|
|
begin
|
|
if not(b) then b := fcoolbands;
|
|
ar := "";
|
|
ctls := controls;
|
|
for i,vi in b.data2 do
|
|
begin
|
|
for j,v in vi do
|
|
begin
|
|
ar+= inttostr(ctls.indexof(v.fctl));
|
|
ar+=",";
|
|
end
|
|
ar[length(ar)] := ";";
|
|
end
|
|
if ar then ar[length(ar):] := "";
|
|
return ar;
|
|
end
|
|
function setarrange(ar);
|
|
begin
|
|
ctls := controls;
|
|
ct := ctls.count-1;
|
|
if ct<0 then return ;
|
|
idxs := 0->(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 setautosize(v);//自动调整
|
|
begin
|
|
nv := v?true:false;
|
|
if nv<>fautosize then
|
|
begin
|
|
fautosize := v;
|
|
if nv then
|
|
begin
|
|
doControlALign();
|
|
end
|
|
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;// max(20,h);
|
|
end
|
|
if (csDesigning in ComponentState) and (length(r)=1 and r[0]<2) then
|
|
begin
|
|
r[0] := 25;
|
|
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<b) then //确定行
|
|
begin
|
|
for j,bsi in flines[i].data do //在行中循环
|
|
begin
|
|
rc := bsi.fctlrect;
|
|
rt := -1;
|
|
if (x>=(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. |